{"version":3,"file":"touchUtils-C7Ut3mIb.mjs","names":["defaultTouchConfig: TouchConfig","p1: Point","p2: Point","touch1: Touch","touch2: Touch","touch: Touch","onGesture: (gesture: TouchEventData) => void","config: Partial<TouchConfig>","event: TouchEvent","enabled: boolean","e: TouchEvent","e: Event","query: string","event: MediaQueryListEvent"],"sources":["../../src/utils/touchUtils.ts"],"sourcesContent":["/**\n * Touch and Mobile Utilities\n *\n * Utilities for handling touch interactions and mobile-specific functionality\n * in Circuit-Bricks. Provides enhanced touch gesture support for circuit\n * manipulation on mobile devices.\n */\n\nimport { useEffect, useRef, useState, useCallback } from 'react';\nimport { Point } from '../schemas/componentSchema';\nimport { isBrowser } from './ssrUtils';\n\n/**\n * Touch gesture types\n */\nexport type TouchGesture = 'tap' | 'double-tap' | 'long-press' | 'pan' | 'pinch' | 'swipe';\n\n/**\n * Touch event data\n */\nexport interface TouchEventData {\n  type: TouchGesture;\n  startPoint: Point;\n  currentPoint: Point;\n  deltaX: number;\n  deltaY: number;\n  distance: number;\n  scale?: number;\n  velocity?: Point;\n  duration: number;\n}\n\n/**\n * Touch gesture configuration\n */\nexport interface TouchConfig {\n  tapThreshold: number; // Maximum movement for tap (px)\n  longPressDelay: number; // Long press delay (ms)\n  doubleTapDelay: number; // Double tap max delay (ms)\n  swipeThreshold: number; // Minimum distance for swipe (px)\n  swipeVelocityThreshold: number; // Minimum velocity for swipe (px/ms)\n  pinchThreshold: number; // Minimum scale change for pinch\n  preventDefaultOnTouch: boolean;\n}\n\n/**\n * Default touch configuration\n */\nconst defaultTouchConfig: TouchConfig = {\n  tapThreshold: 10,\n  longPressDelay: 500,\n  doubleTapDelay: 300,\n  swipeThreshold: 50,\n  swipeVelocityThreshold: 0.5,\n  pinchThreshold: 0.1,\n  preventDefaultOnTouch: true\n};\n\n/**\n * Touch state interface\n */\ninterface TouchState {\n  isActive: boolean;\n  startTime: number;\n  startPoint: Point;\n  currentPoint: Point;\n  lastTapTime: number;\n  touches: Touch[];\n  initialDistance?: number;\n  initialScale: number;\n}\n\n/**\n * Calculate distance between two points\n */\nconst getDistance = (p1: Point, p2: Point): number => {\n  const dx = p2.x - p1.x;\n  const dy = p2.y - p1.y;\n  return Math.sqrt(dx * dx + dy * dy);\n};\n\n/**\n * Calculate distance between two touches\n */\nconst getTouchDistance = (touch1: Touch, touch2: Touch): number => {\n  return getDistance(\n    { x: touch1.clientX, y: touch1.clientY },\n    { x: touch2.clientX, y: touch2.clientY }\n  );\n};\n\n/**\n * Get touch point from touch event\n */\nconst getTouchPoint = (touch: Touch): Point => ({\n  x: touch.clientX,\n  y: touch.clientY\n});\n\n/**\n * Hook for handling touch gestures\n */\nexport const useTouchGestures = (\n  onGesture: (gesture: TouchEventData) => void,\n  config: Partial<TouchConfig> = {}\n) => {\n  const touchConfig = { ...defaultTouchConfig, ...config };\n  const stateRef = useRef<TouchState>({\n    isActive: false,\n    startTime: 0,\n    startPoint: { x: 0, y: 0 },\n    currentPoint: { x: 0, y: 0 },\n    lastTapTime: 0,\n    touches: [],\n    initialScale: 1\n  });\n  const longPressTimerRef = useRef<NodeJS.Timeout | undefined>(undefined);\n\n  const clearLongPressTimer = useCallback(() => {\n    if (longPressTimerRef.current) {\n      clearTimeout(longPressTimerRef.current);\n      longPressTimerRef.current = undefined;\n    }\n  }, []);\n\n  const handleTouchStart = useCallback((event: TouchEvent) => {\n    if (touchConfig.preventDefaultOnTouch) {\n      event.preventDefault();\n    }\n\n    const touch = event.touches[0];\n    const currentTime = Date.now();\n    const touchPoint = getTouchPoint(touch);\n\n    stateRef.current = {\n      isActive: true,\n      startTime: currentTime,\n      startPoint: touchPoint,\n      currentPoint: touchPoint,\n      lastTapTime: stateRef.current.lastTapTime,\n      touches: Array.from(event.touches),\n      initialScale: 1\n    };\n\n    // Set up long press detection\n    longPressTimerRef.current = setTimeout(() => {\n      if (stateRef.current.isActive) {\n        const distance = getDistance(stateRef.current.startPoint, stateRef.current.currentPoint);\n        if (distance < touchConfig.tapThreshold) {\n          onGesture({\n            type: 'long-press',\n            startPoint: stateRef.current.startPoint,\n            currentPoint: stateRef.current.currentPoint,\n            deltaX: 0,\n            deltaY: 0,\n            distance: 0,\n            duration: currentTime - stateRef.current.startTime\n          });\n        }\n      }\n    }, touchConfig.longPressDelay);\n\n    // Handle pinch start\n    if (event.touches.length === 2) {\n      stateRef.current.initialDistance = getTouchDistance(event.touches[0], event.touches[1]);\n    }\n  }, [onGesture, touchConfig]);\n\n  const handleTouchMove = useCallback((event: TouchEvent) => {\n    if (!stateRef.current.isActive) return;\n\n    if (touchConfig.preventDefaultOnTouch) {\n      event.preventDefault();\n    }\n\n    const touch = event.touches[0];\n    const currentPoint = getTouchPoint(touch);\n    const currentTime = Date.now();\n\n    stateRef.current.currentPoint = currentPoint;\n    stateRef.current.touches = Array.from(event.touches);\n\n    const deltaX = currentPoint.x - stateRef.current.startPoint.x;\n    const deltaY = currentPoint.y - stateRef.current.startPoint.y;\n    const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n    const duration = currentTime - stateRef.current.startTime;\n\n    // Clear long press if moved too much\n    if (distance > touchConfig.tapThreshold) {\n      clearLongPressTimer();\n    }\n\n    // Handle pinch gesture\n    if (event.touches.length === 2 && stateRef.current.initialDistance) {\n      const currentDistance = getTouchDistance(event.touches[0], event.touches[1]);\n      const scale = currentDistance / stateRef.current.initialDistance;\n\n      if (Math.abs(scale - stateRef.current.initialScale) > touchConfig.pinchThreshold) {\n        onGesture({\n          type: 'pinch',\n          startPoint: stateRef.current.startPoint,\n          currentPoint,\n          deltaX,\n          deltaY,\n          distance,\n          scale,\n          duration\n        });\n        stateRef.current.initialScale = scale;\n      }\n    }\n    // Handle pan gesture\n    else if (event.touches.length === 1 && distance > touchConfig.tapThreshold) {\n      const velocity = {\n        x: deltaX / Math.max(duration, 1),\n        y: deltaY / Math.max(duration, 1)\n      };\n\n      onGesture({\n        type: 'pan',\n        startPoint: stateRef.current.startPoint,\n        currentPoint,\n        deltaX,\n        deltaY,\n        distance,\n        velocity,\n        duration\n      });\n    }\n  }, [onGesture, touchConfig, clearLongPressTimer]);\n\n  const handleTouchEnd = useCallback((event: TouchEvent) => {\n    if (!stateRef.current.isActive) return;\n\n    if (touchConfig.preventDefaultOnTouch) {\n      event.preventDefault();\n    }\n\n    clearLongPressTimer();\n\n    const currentTime = Date.now();\n    const deltaX = stateRef.current.currentPoint.x - stateRef.current.startPoint.x;\n    const deltaY = stateRef.current.currentPoint.y - stateRef.current.startPoint.y;\n    const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n    const duration = currentTime - stateRef.current.startTime;\n\n    // Handle tap gestures\n    if (distance < touchConfig.tapThreshold && duration < touchConfig.longPressDelay) {\n      const timeSinceLastTap = currentTime - stateRef.current.lastTapTime;\n\n      if (timeSinceLastTap < touchConfig.doubleTapDelay) {\n        // Double tap\n        onGesture({\n          type: 'double-tap',\n          startPoint: stateRef.current.startPoint,\n          currentPoint: stateRef.current.currentPoint,\n          deltaX: 0,\n          deltaY: 0,\n          distance: 0,\n          duration\n        });\n        stateRef.current.lastTapTime = 0; // Reset to prevent triple tap\n      } else {\n        // Single tap\n        onGesture({\n          type: 'tap',\n          startPoint: stateRef.current.startPoint,\n          currentPoint: stateRef.current.currentPoint,\n          deltaX: 0,\n          deltaY: 0,\n          distance: 0,\n          duration\n        });\n        stateRef.current.lastTapTime = currentTime;\n      }\n    }\n    // Handle swipe gestures\n    else if (distance > touchConfig.swipeThreshold) {\n      const velocity = {\n        x: deltaX / Math.max(duration, 1),\n        y: deltaY / Math.max(duration, 1)\n      };\n      const velocityMagnitude = Math.sqrt(velocity.x * velocity.x + velocity.y * velocity.y);\n\n      if (velocityMagnitude > touchConfig.swipeVelocityThreshold) {\n        onGesture({\n          type: 'swipe',\n          startPoint: stateRef.current.startPoint,\n          currentPoint: stateRef.current.currentPoint,\n          deltaX,\n          deltaY,\n          distance,\n          velocity,\n          duration\n        });\n      }\n    }\n\n    stateRef.current.isActive = false;\n  }, [onGesture, touchConfig, clearLongPressTimer]);\n\n  const touchHandlers = {\n    onTouchStart: handleTouchStart,\n    onTouchMove: handleTouchMove,\n    onTouchEnd: handleTouchEnd,\n    onTouchCancel: handleTouchEnd\n  };\n\n  return touchHandlers;\n};\n\n/**\n * Hook for detecting device orientation\n */\nexport const useDeviceOrientation = () => {\n  const [orientation, setOrientation] = useState<'portrait' | 'landscape'>('portrait');\n\n  useEffect(() => {\n    if (!isBrowser()) return;\n\n    const updateOrientation = () => {\n      setOrientation(window.innerHeight > window.innerWidth ? 'portrait' : 'landscape');\n    };\n\n    updateOrientation();\n    window.addEventListener('resize', updateOrientation);\n    window.addEventListener('orientationchange', updateOrientation);\n\n    return () => {\n      window.removeEventListener('resize', updateOrientation);\n      window.removeEventListener('orientationchange', updateOrientation);\n    };\n  }, []);\n\n  return orientation;\n};\n\n/**\n * Hook for safe area insets (for devices with notches)\n */\nexport const useSafeAreaInsets = () => {\n  const [insets, setInsets] = useState({\n    top: 0,\n    right: 0,\n    bottom: 0,\n    left: 0\n  });\n\n  useEffect(() => {\n    if (!isBrowser()) return;\n\n    const updateInsets = () => {\n      const computedStyle = getComputedStyle(document.documentElement);\n      setInsets({\n        top: parseInt(computedStyle.getPropertyValue('env(safe-area-inset-top)') || '0'),\n        right: parseInt(computedStyle.getPropertyValue('env(safe-area-inset-right)') || '0'),\n        bottom: parseInt(computedStyle.getPropertyValue('env(safe-area-inset-bottom)') || '0'),\n        left: parseInt(computedStyle.getPropertyValue('env(safe-area-inset-left)') || '0')\n      });\n    };\n\n    updateInsets();\n    window.addEventListener('resize', updateInsets);\n\n    return () => {\n      window.removeEventListener('resize', updateInsets);\n    };\n  }, []);\n\n  return insets;\n};\n\n/**\n * Prevent zoom on double tap (iOS Safari)\n */\nexport const usePreventZoom = (enabled: boolean = true) => {\n  useEffect(() => {\n    if (!isBrowser() || !enabled) return;\n\n    const preventDefault = (e: TouchEvent) => {\n      if (e.touches.length > 1) {\n        e.preventDefault();\n      }\n    };\n\n    const preventZoom = (e: Event) => {\n      e.preventDefault();\n    };\n\n    document.addEventListener('touchstart', preventDefault, { passive: false });\n    document.addEventListener('gesturestart', preventZoom, { passive: false });\n\n    return () => {\n      document.removeEventListener('touchstart', preventDefault);\n      document.removeEventListener('gesturestart', preventZoom);\n    };\n  }, [enabled]);\n};\n\n/**\n * SSR-safe user agent detection (internal)\n */\nconst useUserAgentInternal = () => {\n  const [userAgent, setUserAgent] = useState('');\n\n  useEffect(() => {\n    if (isBrowser()) {\n      setUserAgent(navigator.userAgent);\n    }\n  }, []);\n\n  return userAgent;\n};\n\n/**\n * SSR-safe media query hook (internal)\n */\nconst useMediaQueryInternal = (query: string): boolean => {\n  const [matches, setMatches] = useState(false);\n\n  useEffect(() => {\n    if (!isBrowser()) return;\n\n    const mediaQuery = window.matchMedia(query);\n    setMatches(mediaQuery.matches);\n\n    const handler = (event: MediaQueryListEvent) => {\n      setMatches(event.matches);\n    };\n\n    mediaQuery.addEventListener('change', handler);\n\n    return () => {\n      mediaQuery.removeEventListener('change', handler);\n    };\n  }, [query]);\n\n  return matches;\n};\n\n/**\n * Detect mobile devices\n */\nexport const useIsMobileTouch = (): boolean => {\n  const userAgent = useUserAgentInternal();\n  const isSmallScreen = useMediaQueryInternal('(max-width: 768px)');\n\n  const isMobileUA = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent);\n\n  return isMobileUA || isSmallScreen;\n};\n\n/**\n * Detect touch support\n */\nexport const useHasTouchSupportTouch = (): boolean => {\n  const [hasTouch, setHasTouch] = useState(false);\n\n  useEffect(() => {\n    if (isBrowser()) {\n      setHasTouch(\n        'ontouchstart' in window ||\n        navigator.maxTouchPoints > 0 ||\n        // @ts-ignore - for older browsers\n        navigator.msMaxTouchPoints > 0\n      );\n    }\n  }, []);\n\n  return hasTouch;\n};\n"],"mappings":"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"}