{"version":3,"file":"index.cjs","sources":[""],"sourcesContent":["import { getWindow } from \"ssr-window\";\r\nimport { isTouchDevice } from \"../../user/isTouchDevice/index.ts\";\r\nimport { bubble } from \"../bubble/index.ts\";\r\n\r\ntype TSupportedEvents =\r\n  | { type: \"pointer\"; start: \"pointerdown\"; move: \"pointermove\"; end: \"pointerup\"; cancel: \"pointercancel\"; leave: \"pointerleave\"; }\r\n  | { type: \"touch\"; start: \"touchstart\"; move: \"touchmove\"; end: \"touchend\"; cancel: \"touchcancel\"; leave: \"touchleave\"; }\r\n  | { type: \"mouse\"; start: \"mousedown\"; move: \"mousemove\"; end: \"mouseup\"; leave: \"mouseleave\"; };\r\n\r\nexport type TOnSwipeArgs = Parameters<typeof onSwipe>;\r\n\r\nexport type TOnSwipeReturn = ReturnType<typeof onSwipe>;\r\n\r\n/**\r\n * Adds a device-agnostic swipe detector for an element (pointer, touch, or mouse).\r\n * Dispatches a \"swipe\" `CustomEvent` or calls the provided callback.\r\n *\r\n * @template TDetail\r\n * @param {Element|Document} el Target to listen for gestures\r\n * @param {{\r\n *   callback?: (detail: TDetail) => void;\r\n *   minDist?: number;\r\n *   maxDist?: number;\r\n *   minTime?: number;\r\n *   maxTime?: number;\r\n * }} [props={}] Swipe configuration\r\n * @param {boolean} [isAutoInit=true] Attach listeners immediately\r\n * @returns {{\r\n *   handler: { start: (e: Event) => void; move: (e: Event) => void; end: (e: Event) => void };\r\n *   addListener: () => void;\r\n *   removeListener: () => void;\r\n * }}\r\n * @throws {TypeError} onSwipe: el must be an Element or Document\r\n * @throws {TypeError} onSwipe: props must be an object\r\n * @throws {TypeError} onSwipe: callback must be a function if provided\r\n * @throws {TypeError} onSwipe: minDist/maxDist/minTime/maxTime must be finite numbers if provided\r\n *\r\n * @example\r\n * onSwipe(document.getElementById(\"box\")!, { callback: ({ dir }) => console.log(dir) });\r\n */\r\nexport const onSwipe = <TDetail extends {\r\n  originEvent: Event;\r\n  dir: \"left\" | \"right\" | \"up\" | \"down\";\r\n  dist: number;\r\n  time: number;\r\n  supportedEvents: TSupportedEvents;\r\n} = {\r\n  originEvent: Event;\r\n  dir: \"left\" | \"right\" | \"up\" | \"down\";\r\n  dist: number;\r\n  time: number;\r\n  supportedEvents: TSupportedEvents;\r\n}>(\r\n  el: Element | Document,\r\n  props: {\r\n    callback?: (detail: TDetail) => void;\r\n    minDist?: number;\r\n    maxDist?: number;\r\n    minTime?: number;\r\n    maxTime?: number;\r\n  } = {},\r\n  isAutoInit: boolean = true\r\n): { handler: { start: (e: Event) => void; move: (e: Event) => void; end: (e: Event) => void; }; addListener: () => void; removeListener: () => void; } => {\r\n  if (!el || typeof (el as any).addEventListener !== \"function\") {\r\n    throw new TypeError(\"onSwipe: el must be an Element or Document\");\r\n  }\r\n  if (props === null || typeof props !== \"object\") {\r\n    throw new TypeError(\"onSwipe: props must be an object\");\r\n  }\r\n  const {\r\n    callback, minDist, maxDist, minTime, maxTime,\r\n  } = props as any;\r\n  if (typeof callback !== \"undefined\" && typeof callback !== \"function\") {\r\n    throw new TypeError(\"onSwipe: callback must be a function if provided\");\r\n  }\r\n  for (const [ k, v ] of Object.entries({\r\n    minDist, maxDist, minTime, maxTime,\r\n  })) {\r\n    if (typeof v !== \"undefined\" && (typeof v !== \"number\" || !Number.isFinite(v))) {\r\n      throw new TypeError(`onSwipe: ${k} must be a finite number if provided`);\r\n    }\r\n  }\r\n\r\n  const settings = {\r\n    minDist: 60,\r\n    maxDist: 120,\r\n    maxTime: 700,\r\n    minTime: 50,\r\n    callback: null as null | ((detail: TDetail) => void),\r\n    ...props,\r\n  };\r\n\r\n  if (settings.maxTime < settings.minTime) {\r\n    settings.maxTime = settings.minTime + 500;\r\n  }\r\n\r\n  if (settings.maxTime < 100 || settings.minTime < 50) {\r\n    settings.maxTime = 700;\r\n    settings.minTime = 50;\r\n  }\r\n\r\n  const eventsUnify = (e: MouseEvent | TouchEvent | PointerEvent | CustomEvent | Event) => {\r\n    const te = e as TouchEvent;\r\n    if (typeof te.changedTouches !== \"undefined\" && te.changedTouches && te.changedTouches.length) {\r\n      return te.changedTouches[0];\r\n    }\r\n    return e as unknown as { pageX?: number; pageY?: number; };\r\n  };\r\n\r\n  const isSupport = {\r\n    pointer: (\"PointerEvent\" in getWindow() || (\"msPointerEnabled\" in (getWindow().navigator as unknown as { msPointerEnabled?: unknown; }))),\r\n    touch: isTouchDevice(),\r\n  };\r\n\r\n  const getSupportedEvents = (): TSupportedEvents => {\r\n    if (isSupport.pointer) {\r\n      return {\r\n        type: \"pointer\",\r\n        start: \"pointerdown\",\r\n        move: \"pointermove\",\r\n        end: \"pointerup\",\r\n        cancel: \"pointercancel\",\r\n        leave: \"pointerleave\",\r\n      };\r\n    }\r\n    if (isSupport.touch) {\r\n      return {\r\n        type: \"touch\",\r\n        start: \"touchstart\",\r\n        move: \"touchmove\",\r\n        end: \"touchend\",\r\n        cancel: \"touchcancel\",\r\n        leave: \"touchleave\",\r\n      };\r\n    }\r\n    return {\r\n      type: \"mouse\",\r\n      start: \"mousedown\",\r\n      move: \"mousemove\",\r\n      end: \"mouseup\",\r\n      leave: \"mouseleave\",\r\n    };\r\n  };\r\n\r\n  const events = getSupportedEvents();\r\n\r\n  let dir: \"none\" | \"left\" | \"right\" | \"up\" | \"down\",\r\n    swipeType: \"none\" | \"left\" | \"right\" | \"up\" | \"down\",\r\n    dist: number,\r\n    isMouse = false,\r\n    isMouseDown = false,\r\n    startX = 0,\r\n    distX = 0,\r\n    startY = 0,\r\n    distY = 0,\r\n    startTime = 0;\r\n\r\n  const checkStart = (e: Event): void => {\r\n    const event: any = eventsUnify(e);\r\n    const t = e as TouchEvent;\r\n    if (isSupport.touch && typeof t.touches !== \"undefined\" && t.touches.length !== 1) {\r\n      return;\r\n    }\r\n    dir = \"none\";\r\n    swipeType = \"none\";\r\n    dist = 0;\r\n    const ce = e as CustomEvent<{ _pageX?: number; _pageY?: number; }>;\r\n    startX = (event.pageX ?? ce?.detail?._pageX ?? 0);\r\n    startY = (event.pageY ?? ce?.detail?._pageY ?? 0);\r\n    startTime = Date.now();\r\n    if (isMouse) {\r\n      isMouseDown = true;\r\n    }\r\n  };\r\n\r\n  const checkMove = (e: Event): void => {\r\n    if (isMouse && !isMouseDown) {\r\n      return;\r\n    }\r\n    const event: any = eventsUnify(e);\r\n    const ce = e as CustomEvent<{ _pageX?: number; _pageY?: number; }>;\r\n    distX = (event.pageX ?? ce?.detail?._pageX ?? 0) - startX;\r\n    distY = (event.pageY ?? ce?.detail?._pageY ?? 0) - startY;\r\n    if (Math.abs(distX) > Math.abs(distY)) {\r\n      dir = (distX < 0) ? \"left\" : \"right\";\r\n    } else {\r\n      dir = (distY < 0) ? \"up\" : \"down\";\r\n    }\r\n  };\r\n\r\n  const checkEnd = (e: Event): void => {\r\n    if (isMouse && !isMouseDown) {\r\n      isMouseDown = false;\r\n      return;\r\n    }\r\n\r\n    const endTime = Date.now();\r\n    const time = endTime - startTime;\r\n\r\n    if (time >= settings.minTime && time <= settings.maxTime) {\r\n      if (Math.abs(distX) >= settings.minDist && Math.abs(distY) <= settings.maxDist) {\r\n        swipeType = dir;\r\n      } else if (Math.abs(distY) >= settings.minDist && Math.abs(distX) <= settings.maxDist) {\r\n        swipeType = dir;\r\n      }\r\n    }\r\n\r\n    dist = (dir === \"left\" || dir === \"right\") ? Math.abs(distX) : Math.abs(distY);\r\n\r\n    const ce = e as CustomEvent<{ _swipeType?: \"left\" | \"right\" | \"up\" | \"down\"; _pageX?: number; _pageY?: number; }>;\r\n    if (ce?.detail?._swipeType) {\r\n      swipeType = ce.detail._swipeType;\r\n    }\r\n\r\n    if (swipeType !== \"none\" && dist >= settings.minDist) {\r\n      const detail = {\r\n        originEvent: e,\r\n        dir: swipeType as \"left\" | \"right\" | \"up\" | \"down\",\r\n        dist,\r\n        time,\r\n        supportedEvents: events as TSupportedEvents,\r\n      } as TDetail;\r\n      if (typeof settings.callback === \"function\") {\r\n        settings.callback(detail);\r\n      } else {\r\n        bubble(el as any, \"swipe\", detail, {\r\n          bubbles: true,\r\n          cancelable: true,\r\n        });\r\n      }\r\n    }\r\n  };\r\n\r\n  const handler = {\r\n    start: (e: Event): void => checkStart(e),\r\n    end: (e: Event): void => checkEnd(e),\r\n    move: (e: Event): void => checkMove(e),\r\n  };\r\n\r\n  if ((isSupport.pointer && !isSupport.touch) || events.type === \"mouse\") {\r\n    isMouse = true;\r\n  }\r\n\r\n  const listenerCtrl = (isBind: boolean = true): void => {\r\n    const action: \"addEventListener\" | \"removeEventListener\" = isBind ? \"addEventListener\" : \"removeEventListener\";\r\n    (el as unknown as EventTarget)[action](events.start, handler.start as EventListener);\r\n    (el as unknown as EventTarget)[action](events.move, handler.move as EventListener);\r\n    (el as unknown as EventTarget)[action](events.end, handler.end as EventListener);\r\n    if (isSupport.pointer && isSupport.touch) {\r\n      (el as unknown as EventTarget)[action](\"lostpointercapture\", handler.end as EventListener);\r\n    }\r\n  };\r\n\r\n  const addListener = (): void => {\r\n    listenerCtrl(true);\r\n  };\r\n\r\n  const removeListener = (): void => {\r\n    listenerCtrl(false);\r\n  };\r\n\r\n  if (isAutoInit) {\r\n    addListener();\r\n  }\r\n\r\n  return {\r\n    handler,\r\n    addListener,\r\n    removeListener,\r\n  };\r\n};\r\n"],"names":["onSwipe","el","props","isAutoInit","addEventListener","TypeError","callback","minDist","maxDist","minTime","maxTime","k","v","Object","entries","Number","isFinite","settings","eventsUnify","e","te","changedTouches","length","isSupport","pointer","getWindow","navigator","touch","isTouchDevice","getSupportedEvents","type","start","move","end","cancel","leave","events","dir","swipeType","dist","isMouse","isMouseDown","startX","distX","startY","distY","startTime","checkStart","event","t","touches","ce","pageX","detail","_pageX","pageY","_pageY","Date","now","checkMove","Math","abs","checkEnd","endTime","time","_swipeType","originEvent","supportedEvents","bubble","bubbles","cancelable","handler","listenerCtrl","isBind","action","addListener","removeListener"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCO,MAAMA,QAAUA,CAarBC,GACAC,MAMI,CAAA,EACJC,WAAsB,QAEtB,IAAKF,WAAcA,GAAWG,mBAAqB,WACjD,MAAM,IAAIC,UAAU,8CAEtB,GAAIH,QAAU,aAAeA,QAAU,SACrC,MAAM,IAAIG,UAAU,oCAEtB,MAAMC,SACJA,SAAQC,QAAEA,QAAOC,QAAEA,QAAOC,QAAEA,QAAOC,QAAEA,SACnCR,MACJ,UAAWI,WAAa,oBAAsBA,WAAa,WACzD,MAAM,IAAID,UAAU,oDAEtB,IAAK,MAAQM,EAAGC,KAAOC,OAAOC,QAAQ,CACpCP,gBAASC,gBAASC,gBAASC,kBAE3B,UAAWE,IAAM,qBAAuBA,IAAM,WAAaG,OAAOC,SAASJ,IACzE,MAAM,IAAIP,UAAU,YAAYM,yCAIpC,MAAMM,SAAW,CACfV,QAAS,GACTC,QAAS,IACTE,QAAS,IACTD,QAAS,GACTH,SAAU,QACPJ,OAGL,GAAIe,SAASP,QAAUO,SAASR,QAC9BQ,SAASP,QAAUO,SAASR,QAAU,IAGxC,GAAIQ,SAASP,QAAU,KAAOO,SAASR,QAAU,GAAI,CACnDQ,SAASP,QAAU,IACnBO,SAASR,QAAU,EACrB,CAEA,MAAMS,YAAeC,IACnB,MAAMC,GAAKD,EACX,UAAWC,GAAGC,iBAAmB,aAAeD,GAAGC,gBAAkBD,GAAGC,eAAeC,OACrF,OAAOF,GAAGC,eAAe,GAE3B,OAAOF,GAGT,MAAMI,UAAY,CAChBC,QAAU,iBAAkBC,UAAAA,aAAgB,qBAAuBA,UAAAA,YAAYC,UAC/EC,MAAOC,MAAAA,iBAGT,MAAMC,mBAAqBA,KACzB,GAAIN,UAAUC,QACZ,MAAO,CACLM,KAAM,UACNC,MAAO,cACPC,KAAM,cACNC,IAAK,YACLC,OAAQ,gBACRC,MAAO,gBAGX,GAAIZ,UAAUI,MACZ,MAAO,CACLG,KAAM,QACNC,MAAO,aACPC,KAAM,YACNC,IAAK,WACLC,OAAQ,cACRC,MAAO,cAGX,MAAO,CACLL,KAAM,QACNC,MAAO,YACPC,KAAM,YACNC,IAAK,UACLE,MAAO,eAIX,MAAMC,OAASP,qBAEf,IAAIQ,IACFC,UACAC,KACAC,QAAU,MACVC,YAAc,MACdC,OAAS,EACTC,MAAQ,EACRC,OAAS,EACTC,MAAQ,EACRC,UAAY,EAEd,MAAMC,WAAc5B,IAClB,MAAM6B,MAAa9B,YAAYC,GAC/B,MAAM8B,EAAI9B,EACV,GAAII,UAAUI,cAAgBsB,EAAEC,UAAY,aAAeD,EAAEC,QAAQ5B,SAAW,EAC9E,OAEFe,IAAM,OACNC,UAAY,OACZC,KAAO,EACP,MAAMY,GAAKhC,EACXuB,OAAUM,MAAMI,OAASD,IAAIE,QAAQC,QAAU,EAC/CV,OAAUI,MAAMO,OAASJ,IAAIE,QAAQG,QAAU,EAC/CV,UAAYW,KAAKC,MACjB,GAAIlB,QACFC,YAAc,MAIlB,MAAMkB,UAAaxC,IACjB,GAAIqB,UAAYC,YACd,OAEF,MAAMO,MAAa9B,YAAYC,GAC/B,MAAMgC,GAAKhC,EACXwB,OAASK,MAAMI,OAASD,IAAIE,QAAQC,QAAU,GAAKZ,OACnDG,OAASG,MAAMO,OAASJ,IAAIE,QAAQG,QAAU,GAAKZ,OACnD,GAAIgB,KAAKC,IAAIlB,OAASiB,KAAKC,IAAIhB,OAC7BR,IAAOM,MAAQ,EAAK,OAAS,aAE7BN,IAAOQ,MAAQ,EAAK,KAAO,QAI/B,MAAMiB,SAAY3C,IAChB,GAAIqB,UAAYC,YAAa,CAC3BA,YAAc,MACd,MACF,CAEA,MAAMsB,QAAUN,KAAKC,MACrB,MAAMM,KAAOD,QAAUjB,UAEvB,GAAIkB,MAAQ/C,SAASR,SAAWuD,MAAQ/C,SAASP,QAC/C,GAAIkD,KAAKC,IAAIlB,QAAU1B,SAASV,SAAWqD,KAAKC,IAAIhB,QAAU5B,SAAST,QACrE8B,UAAYD,SACP,GAAIuB,KAAKC,IAAIhB,QAAU5B,SAASV,SAAWqD,KAAKC,IAAIlB,QAAU1B,SAAST,QAC5E8B,UAAYD,IAIhBE,KAAQF,MAAQ,QAAUA,MAAQ,QAAWuB,KAAKC,IAAIlB,OAASiB,KAAKC,IAAIhB,OAExE,MAAMM,GAAKhC,EACX,GAAIgC,IAAIE,QAAQY,WACd3B,UAAYa,GAAGE,OAAOY,WAGxB,GAAI3B,YAAc,QAAUC,MAAQtB,SAASV,QAAS,CACpD,MAAM8C,OAAS,CACba,YAAa/C,EACbkB,IAAKC,UACLC,UACAyB,UACAG,gBAAiB/B,QAEnB,UAAWnB,SAASX,WAAa,WAC/BW,SAASX,SAAS+C,aAElBe,eAAOnE,GAAW,QAASoD,OAAQ,CACjCgB,QAAS,KACTC,WAAY,MAGlB,GAGF,MAAMC,QAAU,CACdxC,MAAQZ,GAAmB4B,WAAW5B,GACtCc,IAAMd,GAAmB2C,SAAS3C,GAClCa,KAAOb,GAAmBwC,UAAUxC,IAGtC,GAAKI,UAAUC,UAAYD,UAAUI,OAAUS,OAAON,OAAS,QAC7DU,QAAU,KAGZ,MAAMgC,aAAeA,CAACC,OAAkB,QACtC,MAAMC,OAAqDD,OAAS,mBAAqB,sBACxFxE,GAA8ByE,QAAQtC,OAAOL,MAAOwC,QAAQxC,OAC5D9B,GAA8ByE,QAAQtC,OAAOJ,KAAMuC,QAAQvC,MAC3D/B,GAA8ByE,QAAQtC,OAAOH,IAAKsC,QAAQtC,KAC3D,GAAIV,UAAUC,SAAWD,UAAUI,MAChC1B,GAA8ByE,QAAQ,qBAAsBH,QAAQtC,MAIzE,MAAM0C,YAAcA,KAClBH,aAAa,OAGf,MAAMI,eAAiBA,KACrBJ,aAAa,QAGf,GAAIrE,WACFwE,cAGF,MAAO,CACLJ,gBACAI,wBACAC"}