File size: 1,759 Bytes
cb6a2d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
'use client';

/**
 * Touch gesture utilities for mobile interactions.
 */

export function hapticFeedback(
  style: 'light' | 'medium' | 'heavy' = 'light'
): void {
  if (typeof navigator === 'undefined') return;
  if (!('vibrate' in navigator)) return;

  const patterns: Record<string, number> = {
    light: 10,
    medium: 20,
    heavy: 40,
  };

  navigator.vibrate(patterns[style] || 10);
}

export interface SwipeResult {
  direction: 'up' | 'down' | 'left' | 'right';
  distance: number;
}

/**
 * Create a swipe detector for an element.
 */
export function createSwipeDetector(
  element: HTMLElement,
  onSwipe: (result: SwipeResult) => void,
  threshold: number = 50
): () => void {
  let startX = 0;
  let startY = 0;

  function handleTouchStart(e: TouchEvent) {
    startX = e.touches[0].clientX;
    startY = e.touches[0].clientY;
  }

  function handleTouchEnd(e: TouchEvent) {
    const endX = e.changedTouches[0].clientX;
    const endY = e.changedTouches[0].clientY;

    const diffX = endX - startX;
    const diffY = endY - startY;

    const absDiffX = Math.abs(diffX);
    const absDiffY = Math.abs(diffY);

    if (absDiffX < threshold && absDiffY < threshold) return;

    if (absDiffX > absDiffY) {
      onSwipe({
        direction: diffX > 0 ? 'right' : 'left',
        distance: absDiffX,
      });
    } else {
      onSwipe({
        direction: diffY > 0 ? 'down' : 'up',
        distance: absDiffY,
      });
    }
  }

  element.addEventListener('touchstart', handleTouchStart, { passive: true });
  element.addEventListener('touchend', handleTouchEnd, { passive: true });

  return () => {
    element.removeEventListener('touchstart', handleTouchStart);
    element.removeEventListener('touchend', handleTouchEnd);
  };
}