{"version":3,"sources":["../../../../src/elements/useMouseInElement/core.ts"],"sourcesContent":["import { ObservableHint, observable, type Observable, type OpaqueObject } from \"@legendapp/state\";\nimport { peek, type DeepMaybeObservable } from \"@usels/core\";\nimport { resolveWindowSource, type ConfigurableWindow } from \"@shared/configurable\";\nimport type { MaybeEventTarget } from \"../../types\";\nimport { createResizeObserver } from \"../useResizeObserver/core\";\nimport { createMutationObserver } from \"../useMutationObserver/core\";\nimport { createEventListener } from \"../../browser/useEventListener/core\";\n\nexport interface UseMouseInElementOptions extends ConfigurableWindow {\n  /** Also update elementX/Y when mouse is outside the element. Default: true */\n  handleOutside?: boolean;\n  /** Re-calculate on window scroll. Default: true */\n  windowScroll?: boolean;\n  /** Re-calculate on window resize. Default: true */\n  windowResize?: boolean;\n}\n\nexport interface UseMouseInElementReturn {\n  /** Mouse X position relative to the element */\n  elementX$: Observable<number>;\n  /** Mouse Y position relative to the element */\n  elementY$: Observable<number>;\n  /** Element's absolute X position on the page */\n  elementPositionX$: Observable<number>;\n  /** Element's absolute Y position on the page */\n  elementPositionY$: Observable<number>;\n  /** Element width */\n  elementWidth$: Observable<number>;\n  /** Element height */\n  elementHeight$: Observable<number>;\n  /** Whether the mouse is outside the element */\n  isOutside$: Observable<boolean>;\n  /** Global mouse X (clientX) */\n  x$: Observable<number>;\n  /** Global mouse Y (clientY) */\n  y$: Observable<number>;\n  /** Stop all observers and event listeners */\n  stop: () => void;\n}\n\n/**\n * Framework-agnostic mouse-in-element tracker. Must be called inside a\n * `useScope` factory — `mousemove`, `mouseleave`, window scroll/resize\n * listeners as well as ResizeObserver / MutationObserver for the target are\n * all registered via the scope-aware `create*` helpers and cleaned up\n * automatically when the scope disposes. Public API matches the legacy\n * `useMouseInElement` hook.\n */\nexport function createMouseInElement(\n  target: MaybeEventTarget,\n  options?: DeepMaybeObservable<UseMouseInElementOptions>\n): UseMouseInElementReturn {\n  const opts$ = observable(options) as unknown as Observable<UseMouseInElementOptions>;\n\n  // Mount-time toggles — these gate whether the scroll / resize listeners\n  // are registered at all; they are not expected to flip after mount.\n  const peeked = opts$.peek() ?? {};\n  const windowScroll = peeked.windowScroll !== false;\n  const windowResize = peeked.windowResize !== false;\n\n  const win$ = resolveWindowSource(opts$.window as unknown as Observable<unknown>);\n  const doc$ = observable<OpaqueObject<Document> | null>(() => {\n    const win = win$.get();\n    return win?.document ? ObservableHint.opaque(win.document) : null;\n  });\n\n  // Global mouse coordinates (exposed in return)\n  const mouse$ = observable({ x: 0, y: 0 });\n\n  // Element-relative state\n  const state$ = observable({\n    elementX: 0,\n    elementY: 0,\n    elementPositionX: 0,\n    elementPositionY: 0,\n    elementWidth: 0,\n    elementHeight: 0,\n    isOutside: true,\n  });\n\n  // Recalculate element-relative position from current mouse coords.\n  const update = () => {\n    const el = peek(target) as HTMLElement | null;\n    if (!el || !(el instanceof Element)) {\n      state$.isOutside.set(true);\n      return;\n    }\n\n    const rects = Array.from(el.getClientRects());\n    if (!rects.length) return;\n\n    const mx = mouse$.x.peek();\n    const my = mouse$.y.peek();\n    const win = win$.peek();\n    let found = false;\n\n    for (const rect of rects) {\n      if (mx >= rect.left && mx <= rect.right && my >= rect.top && my <= rect.bottom) {\n        state$.assign({\n          elementX: mx - rect.left,\n          elementY: my - rect.top,\n          elementPositionX: rect.left + (win?.scrollX ?? 0),\n          elementPositionY: rect.top + (win?.scrollY ?? 0),\n          elementWidth: rect.width,\n          elementHeight: rect.height,\n          isOutside: false,\n        });\n        found = true;\n        break;\n      }\n    }\n\n    if (!found) {\n      state$.isOutside.set(true);\n      if (opts$.peek()?.handleOutside !== false) {\n        const rect = rects[0];\n        state$.assign({\n          elementX: mx - rect.left,\n          elementY: my - rect.top,\n          elementPositionX: rect.left + (win?.scrollX ?? 0),\n          elementPositionY: rect.top + (win?.scrollY ?? 0),\n          elementWidth: rect.width,\n          elementHeight: rect.height,\n        });\n      }\n    }\n  };\n\n  // Update global mouse coords then recalculate element-relative state.\n  const onMouseMove = (e: MouseEvent) => {\n    mouse$.assign({ x: e.clientX, y: e.clientY });\n    update();\n  };\n\n  const stopMouse = createEventListener(\n    win$ as unknown as Observable<unknown>,\n    \"mousemove\",\n    onMouseMove,\n    { passive: true }\n  );\n\n  // document mouseleave → force isOutside = true\n  const stopLeave = createEventListener(doc$ as unknown as Observable<unknown>, \"mouseleave\", () =>\n    state$.isOutside.set(true)\n  );\n\n  const stopScroll = createEventListener(\n    windowScroll ? (win$ as unknown as Observable<unknown>) : null,\n    \"scroll\",\n    update,\n    { passive: true }\n  );\n  const stopResize = createEventListener(\n    windowResize ? (win$ as unknown as Observable<unknown>) : null,\n    \"resize\",\n    update,\n    { passive: true }\n  );\n\n  // Observe element size changes\n  const { stop: stopRO } = createResizeObserver(target, update);\n\n  // Observe style/class attribute changes (e.g. CSS transitions, class toggles)\n  const { stop: stopMO } = createMutationObserver(target, update, {\n    attributes: true,\n    attributeFilter: [\"style\", \"class\"],\n  });\n\n  const stop = () => {\n    stopMouse();\n    stopLeave();\n    stopScroll();\n    stopResize();\n    stopRO();\n    stopMO();\n  };\n\n  return {\n    elementX$: state$.elementX,\n    elementY$: state$.elementY,\n    elementPositionX$: state$.elementPositionX,\n    elementPositionY$: state$.elementPositionY,\n    elementWidth$: state$.elementWidth,\n    elementHeight$: state$.elementHeight,\n    isOutside$: state$.isOutside,\n    x$: mouse$.x,\n    y$: mouse$.y,\n    stop,\n  };\n}\n"],"mappings":"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","names":[]}