UNPKG

react-haptic

Version:
52 lines (51 loc) 1.55 kB
// src/index.ts import { useCallback, useEffect, useRef } from "react"; var useHaptic = ({ hapticDuration = 100 } = {}) => { const isBrowser = typeof window !== "undefined"; const labelRef = useRef(null); const checkIosDevice = () => { if (!isBrowser) return false; const ua = navigator.userAgent; const isIphone = /iPhone|iPod/.test(ua); const isIpad = /iPad/.test(ua) || /Macintosh/.test(ua) && navigator.maxTouchPoints > 1; return isIphone || isIpad; }; const createHiddenSwitch = () => { const label = document.createElement("label"); const input = document.createElement("input"); label.style.opacity = "0"; label.style.pointerEvents = "none"; label.style.position = "absolute"; label.style.left = "-9999px"; input.type = "checkbox"; input.setAttribute("switch", ""); label.appendChild(input); return { label }; }; const canVibrate = isBrowser && !checkIosDevice() && Boolean(navigator?.vibrate); useEffect(() => { if (!isBrowser) return; const { label } = createHiddenSwitch(); document.body.appendChild(label); labelRef.current = label; return () => { if (label.parentNode === document.body) { document.body.removeChild(label); } }; }, [isBrowser]); const vibrate = useCallback(() => { if (!isBrowser) return; if (canVibrate) { navigator.vibrate(hapticDuration); } else { labelRef.current?.click(); } }, [canVibrate, hapticDuration]); return { vibrate }; }; export { useHaptic };