mirror of
https://github.com/home-assistant/frontend.git
synced 2025-11-09 02:49:51 +00:00
Bottom-sheet swipe to close (#27537)
* WIP new add automation element * WIP new add dialog * revert merge * Add tabs * fix height * Add max-height * Add keybindings and blocks search separation * Fix device translation * add swipe to close for bottom sheet * fix translations, scroll issues, RTL * update target picker selector * Fix bottom sheet padding * Simplify scroll lock * Simplify scroll lock * Improve swipe gesture * Fix methods * Fix race condition --------- Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
This commit is contained in:
116
src/common/util/swipe-gesture-recognizer.ts
Normal file
116
src/common/util/swipe-gesture-recognizer.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
export interface SwipeGestureResult {
|
||||
velocity: number;
|
||||
delta: number;
|
||||
isSwipe: boolean;
|
||||
isDownwardSwipe: boolean;
|
||||
}
|
||||
|
||||
export interface SwipeGestureConfig {
|
||||
velocitySwipeThreshold?: number;
|
||||
movementTimeThreshold?: number;
|
||||
}
|
||||
|
||||
const VELOCITY_SWIPE_THRESHOLD = 0.5; // px/ms
|
||||
const MOVEMENT_TIME_THRESHOLD = 100; // ms
|
||||
|
||||
/**
|
||||
* Recognizes swipe gestures and calculates velocity for touch interactions.
|
||||
* Tracks touch movement and provides velocity-based and position-based gesture detection.
|
||||
*/
|
||||
export class SwipeGestureRecognizer {
|
||||
private _startY = 0;
|
||||
|
||||
private _delta = 0;
|
||||
|
||||
private _startTime = 0;
|
||||
|
||||
private _lastY = 0;
|
||||
|
||||
private _lastTime = 0;
|
||||
|
||||
private _velocityThreshold: number;
|
||||
|
||||
private _movementTimeThreshold: number;
|
||||
|
||||
constructor(config: SwipeGestureConfig = {}) {
|
||||
this._velocityThreshold =
|
||||
config.velocitySwipeThreshold ?? VELOCITY_SWIPE_THRESHOLD; // px/ms
|
||||
this._movementTimeThreshold =
|
||||
config.movementTimeThreshold ?? MOVEMENT_TIME_THRESHOLD; // ms
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize gesture tracking with starting touch position
|
||||
*/
|
||||
public start(clientY: number): void {
|
||||
const now = Date.now();
|
||||
this._startY = clientY;
|
||||
this._startTime = now;
|
||||
this._lastY = clientY;
|
||||
this._lastTime = now;
|
||||
this._delta = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update gesture state during movement
|
||||
* Returns the current delta (negative when dragging down)
|
||||
*/
|
||||
public move(clientY: number): number {
|
||||
const now = Date.now();
|
||||
this._delta = this._startY - clientY;
|
||||
this._lastY = clientY;
|
||||
this._lastTime = now;
|
||||
return this._delta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate final gesture result when touch ends
|
||||
*/
|
||||
public end(): SwipeGestureResult {
|
||||
const velocity = this.getVelocity();
|
||||
const hasSignificantVelocity = Math.abs(velocity) > this._velocityThreshold;
|
||||
|
||||
return {
|
||||
velocity,
|
||||
delta: this._delta,
|
||||
isSwipe: hasSignificantVelocity,
|
||||
isDownwardSwipe: velocity > 0,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current drag delta (negative when dragging down)
|
||||
*/
|
||||
public getDelta(): number {
|
||||
return this._delta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate velocity based on recent movement
|
||||
* Returns 0 if no recent movement detected
|
||||
* Positive velocity means downward swipe
|
||||
*/
|
||||
public getVelocity(): number {
|
||||
const now = Date.now();
|
||||
const timeSinceLastMove = now - this._lastTime;
|
||||
|
||||
// Only consider velocity if the last movement was recent
|
||||
if (timeSinceLastMove >= this._movementTimeThreshold) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const timeDelta = this._lastTime - this._startTime;
|
||||
return timeDelta > 0 ? (this._lastY - this._startY) / timeDelta : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset all tracking state
|
||||
*/
|
||||
public reset(): void {
|
||||
this._startY = 0;
|
||||
this._delta = 0;
|
||||
this._startTime = 0;
|
||||
this._lastY = 0;
|
||||
this._lastTime = 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user