UNPKG

@solid-primitives/mouse

Version:

A collection of Solid Primitives, that capture current mouse cursor position, and help to deal with common related usecases.

95 lines (94 loc) 4.07 kB
import { createHydratableSingletonRoot } from "@solid-primitives/rootless"; import { createDerivedStaticStore, createStaticStore } from "@solid-primitives/static-store"; import { asAccessor } from "@solid-primitives/utils"; import { createEffect, createSignal, onMount, sharedConfig } from "solid-js"; import { isServer } from "solid-js/web"; import { DEFAULT_MOUSE_POSITION, DEFAULT_RELATIVE_ELEMENT_POSITION, getPositionToElement, makeMouseInsideListener, makeMousePositionListener, } from "./common.js"; /** * Attaches event listeners to {@link target} element to provide a reactive object of current mouse position on the page. * @param target (Defaults to `window`) element to attach the listeners to – can be a reactive function * @param options {@link MousePositionOptions} * @returns reactive object of current mouse position on the page * ```ts * { x: number, y: number, sourceType: MouseSourceType, isInside: boolean } * ``` * @see https://github.com/solidjs-community/solid-primitives/tree/main/packages/mouse#createmouseposition * @example * const [el, setEl] = createSignal(ref) * const pos = createMousePosition(el, { touch: false }) * createEffect(() => { * console.log(pos.x, pos.y) * }) */ export function createMousePosition(target, options = {}) { const fallback = { ...DEFAULT_MOUSE_POSITION, ...options.initialValue, }; if (isServer) { return fallback; } const [state, setState] = createStaticStore(fallback); const attachListeners = (el) => { makeMousePositionListener(el, setState, options); makeMouseInsideListener(el, setState.bind(void 0, "isInside"), options); }; if (typeof target !== "function") attachListeners(target); else createEffect(() => attachListeners(target())); return state; } /** * Attaches event listeners to `window` to provide a reactive object of current mouse position on the page. * * This is a [singleton root primitive](https://github.com/solidjs-community/solid-primitives/tree/main/packages/rootless#createSingletonRoot). * @returns reactive object of current mouse position on the page * ```ts * { x: number, y: number, sourceType: MouseSourceType, isInside: boolean } * ``` * @see https://github.com/solidjs-community/solid-primitives/tree/main/packages/mouse#useMousePosition * @example * const pos = useMousePosition() * createEffect(() => { * console.log(pos.x, pos.y) * }) */ export const useMousePosition = /*#__PURE__*/ createHydratableSingletonRoot(createMousePosition.bind(void 0, void 0, void 0)); /** * Provides an autoupdating position relative to an element based on provided page position. * * @param element target `Element` used in calculations * @param pos reactive function returning page position *(relative to the page not window)* * @param options {@link PositionToElementOptions} * @returns Autoupdating position relative to top-left of the target + current bounds of the element. * * @see https://github.com/solidjs-community/solid-primitives/tree/main/packages/mouse#createPositionToElement * * @example * const [el, setEl] = createSignal(ref) * const pos = useMousePosition() * const relative = createPositionToElement(el, () => pos) * createEffect(() => { * console.log(relative.x, relative.y) * }) */ export function createPositionToElement(element, pos, options = {}) { const fallback = { ...DEFAULT_RELATIVE_ELEMENT_POSITION, ...options.initialValue, }; if (isServer) { return fallback; } const isFn = typeof element === "function", isHydrating = sharedConfig.context, getEl = asAccessor(element), [shouldFallback, setShouldFallback] = createSignal(!!isHydrating, { equals: false }); if (isHydrating || isFn) onMount(() => setShouldFallback(false)); return createDerivedStaticStore(() => { let el; if (shouldFallback() || !(el = getEl())) return fallback; const { x, y } = pos(); return getPositionToElement(x, y, el); }); }