{"version":3,"file":"use-long-press.mjs","names":[],"sources":["../../src/use-long-press/use-long-press.ts"],"sourcesContent":["import React, { useEffect, useMemo, useRef } from 'react';\n\nexport type UseLongPressEvent = 'mouse' | 'touch';\n\nexport interface UseLongPressOptions {\n  /** Time in milliseconds to trigger the long press, default is 400ms */\n  threshold?: number;\n\n  /** Input types that can trigger the long press, `['mouse', 'touch']` by default */\n  events?: UseLongPressEvent[];\n\n  /** If set, the long press is canceled when the pointer moves further than the given distance in px from the start position. `true` uses a 10px threshold, a number sets a custom threshold. `false` by default */\n  cancelOnMove?: boolean | number;\n\n  /** Callback triggered when the long press starts */\n  onStart?: (event: React.MouseEvent | React.TouchEvent) => void;\n\n  /** Callback triggered when the long press finishes */\n  onFinish?: (event: React.MouseEvent | React.TouchEvent) => void;\n\n  /** Callback triggered when the long press is canceled */\n  onCancel?: (event: React.MouseEvent | React.TouchEvent) => void;\n}\n\nexport interface UseLongPressReturnValue {\n  onMouseDown?: (event: React.MouseEvent) => void;\n  onMouseUp?: (event: React.MouseEvent) => void;\n  onMouseLeave?: (event: React.MouseEvent) => void;\n  onMouseMove?: (event: React.MouseEvent) => void;\n  onTouchStart?: (event: React.TouchEvent) => void;\n  onTouchEnd?: (event: React.TouchEvent) => void;\n  onTouchCancel?: (event: React.TouchEvent) => void;\n  onTouchMove?: (event: React.TouchEvent) => void;\n}\n\nconst DEFAULT_EVENTS: UseLongPressEvent[] = ['mouse', 'touch'];\nconst DEFAULT_MOVE_THRESHOLD = 10;\n\nexport function useLongPress(\n  onLongPress: (event: React.MouseEvent | React.TouchEvent) => void,\n  options: UseLongPressOptions = {}\n): UseLongPressReturnValue {\n  const {\n    threshold = 400,\n    events = DEFAULT_EVENTS,\n    cancelOnMove = false,\n    onStart,\n    onFinish,\n    onCancel,\n  } = options;\n  const isLongPressActive = useRef(false);\n  const isPressed = useRef(false);\n  const timeout = useRef<number>(-1);\n  const startPosition = useRef<{ x: number; y: number } | null>(null);\n\n  useEffect(() => () => window.clearTimeout(timeout.current), []);\n\n  const eventsKey = events.join(',');\n\n  return useMemo(() => {\n    if (typeof onLongPress !== 'function') {\n      return {} as UseLongPressReturnValue;\n    }\n\n    const moveEnabled = cancelOnMove !== false;\n    const moveThreshold =\n      cancelOnMove === true ? DEFAULT_MOVE_THRESHOLD : cancelOnMove === false ? 0 : cancelOnMove;\n\n    const start = (event: React.MouseEvent | React.TouchEvent) => {\n      if (!isMouseEvent(event) && !isTouchEvent(event)) {\n        return;\n      }\n\n      if (onStart) {\n        onStart(event);\n      }\n\n      startPosition.current = getEventPosition(event);\n      isPressed.current = true;\n      timeout.current = window.setTimeout(() => {\n        onLongPress(event);\n        isLongPressActive.current = true;\n      }, threshold);\n    };\n\n    const cancel = (event: React.MouseEvent | React.TouchEvent) => {\n      if (!isMouseEvent(event) && !isTouchEvent(event)) {\n        return;\n      }\n\n      if (isLongPressActive.current) {\n        if (onFinish) {\n          onFinish(event);\n        }\n      } else if (isPressed.current) {\n        if (onCancel) {\n          onCancel(event);\n        }\n      }\n\n      isLongPressActive.current = false;\n      isPressed.current = false;\n      startPosition.current = null;\n\n      if (timeout.current !== -1) {\n        window.clearTimeout(timeout.current);\n        timeout.current = -1;\n      }\n    };\n\n    const move = (event: React.MouseEvent | React.TouchEvent) => {\n      if (!moveEnabled || !isPressed.current || isLongPressActive.current) {\n        return;\n      }\n\n      const position = getEventPosition(event);\n      if (!position || !startPosition.current) {\n        return;\n      }\n\n      const dx = position.x - startPosition.current.x;\n      const dy = position.y - startPosition.current.y;\n\n      if (Math.sqrt(dx * dx + dy * dy) > moveThreshold) {\n        cancel(event);\n      }\n    };\n\n    const handlers: UseLongPressReturnValue = {};\n\n    if (events.includes('mouse')) {\n      handlers.onMouseDown = start;\n      handlers.onMouseUp = cancel;\n      handlers.onMouseLeave = cancel;\n      if (moveEnabled) {\n        handlers.onMouseMove = move;\n      }\n    }\n\n    if (events.includes('touch')) {\n      handlers.onTouchStart = start;\n      handlers.onTouchEnd = cancel;\n      handlers.onTouchCancel = cancel;\n      if (moveEnabled) {\n        handlers.onTouchMove = move;\n      }\n    }\n\n    return handlers;\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [onLongPress, threshold, onCancel, onFinish, onStart, cancelOnMove, eventsKey]);\n}\n\nfunction getEventPosition(\n  event: React.MouseEvent | React.TouchEvent\n): { x: number; y: number } | null {\n  if (isTouchEvent(event)) {\n    const touch = event.touches[0] ?? event.changedTouches[0];\n    return touch ? { x: touch.clientX, y: touch.clientY } : null;\n  }\n\n  return { x: event.clientX, y: event.clientY };\n}\n\nfunction isTouchEvent(event: React.MouseEvent | React.TouchEvent): event is React.TouchEvent {\n  return window.TouchEvent\n    ? event.nativeEvent instanceof TouchEvent\n    : 'touches' in event.nativeEvent;\n}\n\nfunction isMouseEvent(event: React.MouseEvent | React.TouchEvent): event is React.MouseEvent {\n  return event.nativeEvent instanceof MouseEvent;\n}\n\nexport namespace useLongPress {\n  export type Options = UseLongPressOptions;\n  export type ReturnValue = UseLongPressReturnValue;\n}\n"],"mappings":";;;AAmCA,MAAM,iBAAsC,CAAC,SAAS,OAAO;AAC7D,MAAM,yBAAyB;AAE/B,SAAgB,aACd,aACA,UAA+B,CAAC,GACP;CACzB,MAAM,EACJ,YAAY,KACZ,SAAS,gBACT,eAAe,OACf,SACA,UACA,aACE;CACJ,MAAM,oBAAoB,OAAO,KAAK;CACtC,MAAM,YAAY,OAAO,KAAK;CAC9B,MAAM,UAAU,OAAe,EAAE;CACjC,MAAM,gBAAgB,OAAwC,IAAI;CAElE,sBAAsB,OAAO,aAAa,QAAQ,OAAO,GAAG,CAAC,CAAC;CAI9D,OAAO,cAAc;EACnB,IAAI,OAAO,gBAAgB,YACzB,OAAO,CAAC;EAGV,MAAM,cAAc,iBAAiB;EACrC,MAAM,gBACJ,iBAAiB,OAAO,yBAAyB,iBAAiB,QAAQ,IAAI;EAEhF,MAAM,SAAS,UAA+C;GAC5D,IAAI,CAAC,aAAa,KAAK,KAAK,CAAC,aAAa,KAAK,GAC7C;GAGF,IAAI,SACF,QAAQ,KAAK;GAGf,cAAc,UAAU,iBAAiB,KAAK;GAC9C,UAAU,UAAU;GACpB,QAAQ,UAAU,OAAO,iBAAiB;IACxC,YAAY,KAAK;IACjB,kBAAkB,UAAU;GAC9B,GAAG,SAAS;EACd;EAEA,MAAM,UAAU,UAA+C;GAC7D,IAAI,CAAC,aAAa,KAAK,KAAK,CAAC,aAAa,KAAK,GAC7C;GAGF,IAAI,kBAAkB;QAChB,UACF,SAAS,KAAK;GAAA,OAEX,IAAI,UAAU;QACf,UACF,SAAS,KAAK;GAAA;GAIlB,kBAAkB,UAAU;GAC5B,UAAU,UAAU;GACpB,cAAc,UAAU;GAExB,IAAI,QAAQ,YAAY,IAAI;IAC1B,OAAO,aAAa,QAAQ,OAAO;IACnC,QAAQ,UAAU;GACpB;EACF;EAEA,MAAM,QAAQ,UAA+C;GAC3D,IAAI,CAAC,eAAe,CAAC,UAAU,WAAW,kBAAkB,SAC1D;GAGF,MAAM,WAAW,iBAAiB,KAAK;GACvC,IAAI,CAAC,YAAY,CAAC,cAAc,SAC9B;GAGF,MAAM,KAAK,SAAS,IAAI,cAAc,QAAQ;GAC9C,MAAM,KAAK,SAAS,IAAI,cAAc,QAAQ;GAE9C,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE,IAAI,eACjC,OAAO,KAAK;EAEhB;EAEA,MAAM,WAAoC,CAAC;EAE3C,IAAI,OAAO,SAAS,OAAO,GAAG;GAC5B,SAAS,cAAc;GACvB,SAAS,YAAY;GACrB,SAAS,eAAe;GACxB,IAAI,aACF,SAAS,cAAc;EAE3B;EAEA,IAAI,OAAO,SAAS,OAAO,GAAG;GAC5B,SAAS,eAAe;GACxB,SAAS,aAAa;GACtB,SAAS,gBAAgB;GACzB,IAAI,aACF,SAAS,cAAc;EAE3B;EAEA,OAAO;CAET,GAAG;EAAC;EAAa;EAAW;EAAU;EAAU;EAAS;EA7FvC,OAAO,KAAK,GA6FiD;CAAC,CAAC;AACnF;AAEA,SAAS,iBACP,OACiC;CACjC,IAAI,aAAa,KAAK,GAAG;EACvB,MAAM,QAAQ,MAAM,QAAQ,MAAM,MAAM,eAAe;EACvD,OAAO,QAAQ;GAAE,GAAG,MAAM;GAAS,GAAG,MAAM;EAAQ,IAAI;CAC1D;CAEA,OAAO;EAAE,GAAG,MAAM;EAAS,GAAG,MAAM;CAAQ;AAC9C;AAEA,SAAS,aAAa,OAAuE;CAC3F,OAAO,OAAO,aACV,MAAM,uBAAuB,aAC7B,aAAa,MAAM;AACzB;AAEA,SAAS,aAAa,OAAuE;CAC3F,OAAO,MAAM,uBAAuB;AACtC"}