{"version":3,"file":"hover.mjs","sources":["../../../src/gestures/hover.ts"],"sourcesContent":["import { ElementOrSelector } from \"../utils/resolve-elements\"\nimport { isDragActive } from \"./drag/state/is-active\"\nimport { EventOptions } from \"./types\"\nimport { setupGesture } from \"./utils/setup\"\n\n/**\n * A function to be called when a hover gesture starts.\n *\n * This function can optionally return a function that will be called\n * when the hover gesture ends.\n *\n * @public\n */\nexport type OnHoverStartEvent = (\n    element: Element,\n    event: PointerEvent\n) => void | OnHoverEndEvent\n\n/**\n * A function to be called when a hover gesture ends.\n *\n * @public\n */\nexport type OnHoverEndEvent = (event: PointerEvent) => void\n\nfunction isValidHover(event: PointerEvent) {\n    return !(event.pointerType === \"touch\" || isDragActive())\n}\n\n/**\n * Create a hover gesture. hover() is different to .addEventListener(\"pointerenter\")\n * in that it has an easier syntax, filters out polyfilled touch events, interoperates\n * with drag gestures, and automatically removes the \"pointerennd\" event listener when the hover ends.\n *\n * @public\n */\nexport function hover(\n    elementOrSelector: ElementOrSelector,\n    onHoverStart: OnHoverStartEvent,\n    options: EventOptions = {}\n): VoidFunction {\n    const [elements, eventOptions, cancel] = setupGesture(\n        elementOrSelector,\n        options\n    )\n\n    elements.forEach((element) => {\n        let isPressed = false\n        let deferredHoverEnd = false\n        let hoverEndCallback: OnHoverEndEvent | undefined\n\n        const removePointerLeave = () => {\n            element.removeEventListener(\n                \"pointerleave\",\n                onPointerLeave as EventListener\n            )\n        }\n\n        const endHover = (event: PointerEvent) => {\n            if (hoverEndCallback) {\n                hoverEndCallback(event)\n                hoverEndCallback = undefined\n            }\n            removePointerLeave()\n        }\n\n        const onPointerUp = (event: Event) => {\n            isPressed = false\n            window.removeEventListener(\n                \"pointerup\",\n                onPointerUp as EventListener\n            )\n            window.removeEventListener(\n                \"pointercancel\",\n                onPointerUp as EventListener\n            )\n\n            if (deferredHoverEnd) {\n                deferredHoverEnd = false\n                endHover(event as PointerEvent)\n            }\n        }\n\n        const onPointerDown = () => {\n            isPressed = true\n            window.addEventListener(\n                \"pointerup\",\n                onPointerUp as EventListener,\n                eventOptions\n            )\n            window.addEventListener(\n                \"pointercancel\",\n                onPointerUp as EventListener,\n                eventOptions\n            )\n        }\n\n        const onPointerLeave = (leaveEvent: PointerEvent) => {\n            if (leaveEvent.pointerType === \"touch\") return\n\n            if (isPressed) {\n                deferredHoverEnd = true\n                return\n            }\n\n            endHover(leaveEvent)\n        }\n\n        const onPointerEnter = (enterEvent: PointerEvent) => {\n            if (!isValidHover(enterEvent)) return\n\n            deferredHoverEnd = false\n\n            const onHoverEnd = onHoverStart(\n                element as Element,\n                enterEvent\n            )\n\n            if (typeof onHoverEnd !== \"function\") return\n\n            hoverEndCallback = onHoverEnd\n\n            element.addEventListener(\n                \"pointerleave\",\n                onPointerLeave as EventListener,\n                eventOptions\n            )\n        }\n\n        element.addEventListener(\n            \"pointerenter\",\n            onPointerEnter as EventListener,\n            eventOptions\n        )\n        element.addEventListener(\n            \"pointerdown\",\n            onPointerDown as EventListener,\n            eventOptions\n        )\n    })\n\n    return cancel\n}\n"],"names":[],"mappings":";;;AAyBA,SAAS,YAAY,CAAC,KAAmB,EAAA;IACrC,OAAO,EAAE,KAAK,CAAC,WAAW,KAAK,OAAO,IAAI,YAAY,EAAE,CAAC,CAAA;AAC7D,CAAC;AAED;;;;;;AAMG;AACG,SAAU,KAAK,CACjB,iBAAoC,EACpC,YAA+B,EAC/B,UAAwB,EAAE,EAAA;AAE1B,IAAA,MAAM,CAAC,QAAQ,EAAE,YAAY,EAAE,MAAM,CAAC,GAAG,YAAY,CACjD,iBAAiB,EACjB,OAAO,CACV,CAAA;AAED,IAAA,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,KAAI;QACzB,IAAI,SAAS,GAAG,KAAK,CAAA;QACrB,IAAI,gBAAgB,GAAG,KAAK,CAAA;AAC5B,QAAA,IAAI,gBAA6C,CAAA;QAEjD,MAAM,kBAAkB,GAAG,MAAK;AAC5B,YAAA,OAAO,CAAC,mBAAmB,CACvB,cAAc,EACd,cAA+B,CAClC,CAAA;AACL,SAAC,CAAA;AAED,QAAA,MAAM,QAAQ,GAAG,CAAC,KAAmB,KAAI;YACrC,IAAI,gBAAgB,EAAE;gBAClB,gBAAgB,CAAC,KAAK,CAAC,CAAA;gBACvB,gBAAgB,GAAG,SAAS,CAAA;aAC/B;AACD,YAAA,kBAAkB,EAAE,CAAA;AACxB,SAAC,CAAA;AAED,QAAA,MAAM,WAAW,GAAG,CAAC,KAAY,KAAI;YACjC,SAAS,GAAG,KAAK,CAAA;AACjB,YAAA,MAAM,CAAC,mBAAmB,CACtB,WAAW,EACX,WAA4B,CAC/B,CAAA;AACD,YAAA,MAAM,CAAC,mBAAmB,CACtB,eAAe,EACf,WAA4B,CAC/B,CAAA;YAED,IAAI,gBAAgB,EAAE;gBAClB,gBAAgB,GAAG,KAAK,CAAA;gBACxB,QAAQ,CAAC,KAAqB,CAAC,CAAA;aAClC;AACL,SAAC,CAAA;QAED,MAAM,aAAa,GAAG,MAAK;YACvB,SAAS,GAAG,IAAI,CAAA;YAChB,MAAM,CAAC,gBAAgB,CACnB,WAAW,EACX,WAA4B,EAC5B,YAAY,CACf,CAAA;YACD,MAAM,CAAC,gBAAgB,CACnB,eAAe,EACf,WAA4B,EAC5B,YAAY,CACf,CAAA;AACL,SAAC,CAAA;AAED,QAAA,MAAM,cAAc,GAAG,CAAC,UAAwB,KAAI;AAChD,YAAA,IAAI,UAAU,CAAC,WAAW,KAAK,OAAO;gBAAE,OAAM;YAE9C,IAAI,SAAS,EAAE;gBACX,gBAAgB,GAAG,IAAI,CAAA;gBACvB,OAAM;aACT;YAED,QAAQ,CAAC,UAAU,CAAC,CAAA;AACxB,SAAC,CAAA;AAED,QAAA,MAAM,cAAc,GAAG,CAAC,UAAwB,KAAI;AAChD,YAAA,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC;gBAAE,OAAM;YAErC,gBAAgB,GAAG,KAAK,CAAA;YAExB,MAAM,UAAU,GAAG,YAAY,CAC3B,OAAkB,EAClB,UAAU,CACb,CAAA;YAED,IAAI,OAAO,UAAU,KAAK,UAAU;gBAAE,OAAM;YAE5C,gBAAgB,GAAG,UAAU,CAAA;YAE7B,OAAO,CAAC,gBAAgB,CACpB,cAAc,EACd,cAA+B,EAC/B,YAAY,CACf,CAAA;AACL,SAAC,CAAA;QAED,OAAO,CAAC,gBAAgB,CACpB,cAAc,EACd,cAA+B,EAC/B,YAAY,CACf,CAAA;QACD,OAAO,CAAC,gBAAgB,CACpB,aAAa,EACb,aAA8B,EAC9B,YAAY,CACf,CAAA;AACL,KAAC,CAAC,CAAA;AAEF,IAAA,OAAO,MAAM,CAAA;AACjB;;;;"}