@solid-primitives/mouse
Advanced tools
Comparing version 1.2.0 to 2.0.0
@@ -0,17 +1,28 @@ | ||
import { Position, MaybeAccessor } from '@solid-primitives/utils'; | ||
import { Accessor } from 'solid-js'; | ||
import { MaybeAccessor } from '@solid-primitives/utils'; | ||
interface MouseOptions { | ||
declare type MouseSourceType = "mouse" | "touch" | null; | ||
declare type MousePosition = Position & { | ||
sourceType: MouseSourceType; | ||
}; | ||
declare type MousePositionInside = MousePosition & { | ||
isInside: boolean; | ||
}; | ||
interface PositionRelativeToElement extends Position { | ||
top: number; | ||
left: number; | ||
width: number; | ||
height: number; | ||
isInside: boolean; | ||
} | ||
interface UseTouchOptions { | ||
/** | ||
* Listen to `touchmove` events | ||
* Listen to touch events. If enabled, position will be updated on `touchstart` event. | ||
* @default true | ||
*/ | ||
touch?: boolean; | ||
} | ||
interface FollowTouchOptions { | ||
/** | ||
* Initial values | ||
* @default { x:0, y:0 } | ||
*/ | ||
initialValue?: Position; | ||
/** | ||
* If enabled, position will be updated on touchmove event. | ||
* If enabled, position will be updated on `touchmove` event. | ||
* @default true | ||
@@ -21,121 +32,105 @@ */ | ||
} | ||
declare type MouseSourceType = "mouse" | "touch" | null; | ||
/** | ||
* Listens to the global mouse events, providing a reactive up-to-date position of the cursor on the page. | ||
* | ||
* @param options | ||
* @returns Accessors for current x & y position, and source of the last cursor movement | ||
* | ||
* @see https://github.com/solidjs-community/solid-primitives/tree/main/packages/mouse#createmouseposition | ||
* | ||
* @example | ||
* const [{ x, y, sourceType }, { stop, start }] = createMousePosition({ touch: false }) | ||
* Attaches event listeners to provided targat, listeneing for changes to the mouse/touch position. | ||
* @param target | ||
* ```ts | ||
* HTMLElement | Window | Document | ||
* ``` | ||
* @param callback function fired on every position change | ||
* @param options {@link UseTouchOptions} & {@link FollowTouchOptions} | ||
* @returns function removing all event listeners | ||
*/ | ||
declare function createMousePosition(options?: MouseOptions): [ | ||
getters: { | ||
x: Accessor<number>; | ||
y: Accessor<number>; | ||
sourceType: Accessor<MouseSourceType>; | ||
}, | ||
clear: VoidFunction | ||
]; | ||
interface Position { | ||
x: number; | ||
y: number; | ||
} | ||
interface RelativeToElementValues extends Position { | ||
top: number; | ||
left: number; | ||
width: number; | ||
height: number; | ||
} | ||
declare function makeMousePositionListener(target: HTMLElement | Window | Document | undefined, callback: (position: MousePosition) => void, options?: UseTouchOptions & FollowTouchOptions): VoidFunction; | ||
/** | ||
* Attaches event listeners to provided targat, listening for mouse/touch entering/leaving the element. | ||
* @param target | ||
* ```ts | ||
* HTMLElement | Window | Document | ||
* ``` | ||
* @param callback function fired on mouse leaving or entering the element | ||
* @param options {@link UseTouchOptions} | ||
* @returns function removing all event listeners | ||
*/ | ||
declare function makeMouseInsideListener(target: HTMLElement | Window | Document | undefined, callback: (isInside: boolean) => void, options?: UseTouchOptions): VoidFunction; | ||
/** | ||
* Turn position relative to the page, into position relative to an element. | ||
*/ | ||
declare const posRelativeToElement: (pageX: number, pageY: number, el: Element) => RelativeToElementValues; | ||
declare const getPositionToElement: (pageX: number, pageY: number, el: Element) => PositionRelativeToElement; | ||
/** | ||
* Turn position relative to the page, into position relative to an element. Clamped to the element bounds. | ||
*/ | ||
declare const getPositionInElement: (pageX: number, pageY: number, el: Element) => PositionRelativeToElement; | ||
/** | ||
* Turn position relative to the page, into position relative to the screen. | ||
*/ | ||
declare const posRelativeToScreen: (pageX: number, pageY: number) => Position; | ||
declare const getPositionToScreen: (pageX: number, pageY: number) => Position; | ||
interface MouseOnScreenOptions { | ||
interface MousePositionOptions extends UseTouchOptions, FollowTouchOptions { | ||
/** | ||
* Listen to touch events | ||
* @default true | ||
* Initial values | ||
* @default { x: 0, y: 0, isInside: false, sourceType: null } | ||
*/ | ||
touch?: boolean; | ||
initialValue?: Partial<MousePositionInside>; | ||
} | ||
interface PositionToElementOptions extends UseTouchOptions, FollowTouchOptions { | ||
/** | ||
* Initial value | ||
* @default false | ||
* @default { x: 0, y: 0, top: 0, left: 0, width: 0, height: 0, isInside: false } | ||
*/ | ||
initialValue?: boolean; | ||
initialValue?: Partial<PositionRelativeToElement>; | ||
} | ||
/** | ||
* *Is the cursor on screen?* | ||
* | ||
* @param options - | ||
* - touch - *Listen to touch events* | ||
* - initialValue | ||
* | ||
* 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 [isMouseOnScreen, { start, stop }] = createMouseOnScreen(true); | ||
* const [el, setEl] = createSignal(ref) | ||
* const pos = createMousePosition(el, { touch: false }) | ||
* createEffect(() => { | ||
* console.log(pos.x, pos.y) | ||
* }) | ||
*/ | ||
declare function createMouseOnScreen(initialValue?: boolean): [onScreen: Accessor<boolean>, clear: VoidFunction]; | ||
declare function createMouseOnScreen(options?: MouseOnScreenOptions): [onScreen: Accessor<boolean>, clear: VoidFunction]; | ||
declare function createMousePosition(target?: MaybeAccessor<Window | Document | HTMLElement>, options?: MousePositionOptions): MousePositionInside; | ||
/** | ||
* Listens to mouse (and touch) events inside the element. | ||
* Attaches event listeners to `window` to provide a reactive object of current mouse position on the page. | ||
* | ||
* @param element target element *— if passed as a signal, will update on change* | ||
* @param options | ||
* @returns Autoupdating position of cursor inside the element; source of the last cursor movement | ||
* | ||
* @see https://github.com/solidjs-community/solid-primitives/tree/main/packages/mouse#createmouseinelement | ||
* | ||
* This is a [shared root primitive](https://github.com/solidjs-community/solid-primitives/tree/main/packages/rootless#createSharedRoot). | ||
* @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 [{ x, y, sourceType, isInside }, { stop, start }] = createMouseInElement(() => myRef, { followTouch: false }) | ||
* const pos = useMousePosition() | ||
* createEffect(() => { | ||
* console.log(pos.x, pos.y) | ||
* }) | ||
*/ | ||
declare function createMouseInElement(element: MaybeAccessor<HTMLElement>, options?: MouseOptions): [ | ||
getters: { | ||
x: Accessor<number>; | ||
y: Accessor<number>; | ||
sourceType: Accessor<MouseSourceType>; | ||
isInside: Accessor<boolean>; | ||
}, | ||
clear: VoidFunction | ||
]; | ||
declare type InitialValues = Partial<RelativeToElementValues>; | ||
interface PositionToElementOptions extends Omit<MouseOptions, "initialValue"> { | ||
initialValue?: InitialValues; | ||
} | ||
declare const useMousePosition: () => MousePositionInside; | ||
/** | ||
* Provides an autoupdating position relative to an element. Can be used with existing position signals, or let it get the current cursor position itself. | ||
* Provides an autoupdating position relative to an element based on provided page position. | ||
* | ||
* @param element target `Element` | ||
* @param pos Your existing position values, or `undefined` to capture mouse position automatically | ||
* @param options | ||
* @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#createmousetoelement | ||
* @see https://github.com/solidjs-community/solid-primitives/tree/main/packages/mouse#createPositionToElement | ||
* | ||
* @example | ||
* const [{ x, y, top, left, width, height, isInside }, manualUpdate] = createMouseToElement(() => myRef) | ||
* const [el, setEl] = createSignal(ref) | ||
* const pos = useMousePosition() | ||
* const relative = createPositionToElement(el, () => pos) | ||
* createEffect(() => { | ||
* console.log(relative.x, relative.y) | ||
* }) | ||
*/ | ||
declare function createMouseToElement(element: MaybeAccessor<Element>, pos?: Accessor<Position> | { | ||
x: MaybeAccessor<number>; | ||
y: MaybeAccessor<number>; | ||
}, options?: PositionToElementOptions): [ | ||
getters: { | ||
x: Accessor<number>; | ||
y: Accessor<number>; | ||
top: Accessor<number>; | ||
left: Accessor<number>; | ||
width: Accessor<number>; | ||
height: Accessor<number>; | ||
isInside: Accessor<boolean>; | ||
}, | ||
update: VoidFunction | ||
]; | ||
declare function createPositionToElement(element: Element | Accessor<Element | undefined>, pos: Accessor<Position>, options?: PositionToElementOptions): PositionRelativeToElement; | ||
export { InitialValues, MouseOnScreenOptions, MouseOptions, MouseSourceType, Position, PositionToElementOptions, RelativeToElementValues, createMouseInElement, createMouseOnScreen, createMousePosition, createMouseToElement, posRelativeToElement, posRelativeToScreen }; | ||
export { FollowTouchOptions, MousePosition, MousePositionInside, MousePositionOptions, MouseSourceType, PositionRelativeToElement, PositionToElementOptions, UseTouchOptions, createMousePosition, createPositionToElement, getPositionInElement, getPositionToElement, getPositionToScreen, makeMouseInsideListener, makeMousePositionListener, useMousePosition }; |
@@ -1,213 +0,20 @@ | ||
// src/mousePosition.ts | ||
import { isClient, createCallbackStack } from "@solid-primitives/utils"; | ||
import { batch, createSignal } from "solid-js"; | ||
// src/common.ts | ||
import { createEventListener } from "@solid-primitives/event-listener"; | ||
var addListener = (el, ev, cb, options = { passive: true }) => createEventListener(el, ev, cb, options); | ||
// src/mousePosition.ts | ||
function createMousePosition(options = {}) { | ||
const { touch = true, followTouch = true, initialValue = { x: 0, y: 0 } } = options; | ||
const [x, setX] = createSignal(initialValue.x); | ||
const [y, setY] = createSignal(initialValue.y); | ||
const [sourceType, setSourceType] = createSignal(null); | ||
const mouseHandler = (event) => batch(() => { | ||
setX(event.pageX); | ||
setY(event.pageY); | ||
setSourceType("mouse"); | ||
}); | ||
const touchHandler = (event) => { | ||
if (!event.touches.length) | ||
return; | ||
batch(() => { | ||
setX(event.touches[0].clientX); | ||
setY(event.touches[0].clientY); | ||
setSourceType("touch"); | ||
}); | ||
}; | ||
const toCleanup = createCallbackStack(); | ||
const start = () => { | ||
if (!isClient) | ||
return; | ||
toCleanup.execute(); | ||
toCleanup.push(addListener(window, "mousemove", mouseHandler)); | ||
toCleanup.push(addListener(window, "dragover", mouseHandler)); | ||
if (touch) { | ||
toCleanup.push(addListener(window, "touchstart", touchHandler)); | ||
if (followTouch) | ||
toCleanup.push(addListener(window, "touchmove", touchHandler)); | ||
} | ||
}; | ||
start(); | ||
return [ | ||
{ | ||
x, | ||
y, | ||
sourceType | ||
}, | ||
toCleanup.execute | ||
]; | ||
} | ||
var posRelativeToElement = (pageX, pageY, el) => { | ||
const bounds = el.getBoundingClientRect(), top = bounds.top + window.screenY, left = bounds.left + window.scrollX; | ||
return { | ||
x: pageX - left, | ||
y: pageY - top, | ||
top, | ||
left, | ||
width: bounds.width, | ||
height: bounds.height | ||
}; | ||
}; | ||
var posRelativeToScreen = (pageX, pageY) => ({ | ||
x: pageX - window.scrollX, | ||
y: pageY - window.screenY | ||
}); | ||
// src/mouseOnScreen.ts | ||
import { isClient as isClient2, createCallbackStack as createCallbackStack2 } from "@solid-primitives/utils"; | ||
import { createMemo, createSignal as createSignal2 } from "solid-js"; | ||
function createMouseOnScreen(a = {}) { | ||
var _a, _b; | ||
let touch; | ||
let initialValue; | ||
if (typeof a === "object") { | ||
touch = (_a = a == null ? void 0 : a.touch) != null ? _a : true; | ||
initialValue = (_b = a == null ? void 0 : a.initialValue) != null ? _b : false; | ||
} else { | ||
touch = true; | ||
initialValue = a != null ? a : null; | ||
} | ||
const [mouseOnScreen, setMouseOnScreen] = createSignal2(initialValue); | ||
const [touchOnScreen, setTouchOnScreen] = createSignal2(touch ? initialValue : false); | ||
const onScreen = createMemo(touch ? () => mouseOnScreen() || touchOnScreen() : () => mouseOnScreen()); | ||
const toCleanup = createCallbackStack2(); | ||
const start = () => { | ||
if (!isClient2) | ||
return; | ||
toCleanup.execute(); | ||
toCleanup.push(addListener(document, "mouseenter", () => setMouseOnScreen(true)), addListener(document, "mousemove", () => setMouseOnScreen(true), { | ||
passive: true, | ||
once: true | ||
}), addListener(document, "mouseleave", () => setMouseOnScreen(false))); | ||
if (touch) | ||
toCleanup.push(addListener(window, "touchstart", () => setTouchOnScreen(true)), addListener(window, "touchend", () => setTouchOnScreen(false))); | ||
}; | ||
start(); | ||
return [onScreen, toCleanup.execute]; | ||
} | ||
// src/mouseInElement.ts | ||
import { access, createCallbackStack as createCallbackStack3 } from "@solid-primitives/utils"; | ||
import { createComputed, createSignal as createSignal3, onMount } from "solid-js"; | ||
function createMouseInElement(element, options = {}) { | ||
const { touch = true, followTouch = true, initialValue = { x: 0, y: 0 } } = options; | ||
const [x, setX] = createSignal3(initialValue.x); | ||
const [y, setY] = createSignal3(initialValue.y); | ||
const [sourceType, setSourceType] = createSignal3(null); | ||
const [isInside, setIsInside] = createSignal3(false); | ||
const handleMouseMove = (e, el) => { | ||
const { top, left } = el.getBoundingClientRect(); | ||
setX(e.pageX - left - window.pageXOffset); | ||
setY(e.pageY - top - window.pageYOffset); | ||
setSourceType("mouse"); | ||
}; | ||
const handleTouchMove = (e, el) => { | ||
const { top, left } = el.getBoundingClientRect(); | ||
if (!e.touches.length) | ||
return; | ||
setX(e.touches[0].clientX - left - window.pageXOffset); | ||
setY(e.touches[0].clientY - top - window.pageYOffset); | ||
setSourceType("touch"); | ||
}; | ||
const toCleanup = createCallbackStack3(); | ||
const start = (el = access(element)) => { | ||
toCleanup.execute(); | ||
if (!el) | ||
return; | ||
toCleanup.push(addListener(el, "mouseover", () => setIsInside(true)), addListener(el, "mouseout", () => setIsInside(false)), addListener(el, "mousemove", (e) => handleMouseMove(e, el))); | ||
if (touch) { | ||
toCleanup.push(addListener(el, "touchstart", (e) => { | ||
setIsInside(true); | ||
handleTouchMove(e, el); | ||
}), addListener(el, "touchend", () => setIsInside(false))); | ||
if (followTouch) | ||
toCleanup.push(addListener(el, "touchmove", (e) => handleTouchMove(e, el))); | ||
} | ||
}; | ||
access(element) ? createComputed(() => start()) : onMount(() => createComputed(() => start())); | ||
return [ | ||
{ | ||
x, | ||
y, | ||
sourceType, | ||
isInside | ||
}, | ||
toCleanup.execute | ||
]; | ||
} | ||
// src/mouseToElement.ts | ||
import { omit } from "@solid-primitives/immutable"; | ||
import { access as access2 } from "@solid-primitives/utils"; | ||
import { batch as batch2, createComputed as createComputed2, createMemo as createMemo2, createSignal as createSignal4, onMount as onMount2 } from "solid-js"; | ||
function createMouseToElement(element, pos, options = {}) { | ||
var _a, _b, _c, _d, _e, _f; | ||
const { initialValue = {} } = options; | ||
let pageX; | ||
let pageY; | ||
if (typeof pos === "function") { | ||
pageX = () => pos().x; | ||
pageY = () => pos().y; | ||
} else if (typeof pos === "object") { | ||
pageX = typeof pos.x === "function" ? pos.x : () => pos.x; | ||
pageY = typeof pos.y === "function" ? pos.y : () => pos.y; | ||
} else { | ||
const [mouse] = createMousePosition(omit(options, "initialValue")); | ||
pageX = mouse.x; | ||
pageY = mouse.y; | ||
} | ||
const [x, setX] = createSignal4((_a = initialValue.x) != null ? _a : 0); | ||
const [y, setY] = createSignal4((_b = initialValue.y) != null ? _b : 0); | ||
const [top, setTop] = createSignal4((_c = initialValue.top) != null ? _c : 0); | ||
const [left, setLeft] = createSignal4((_d = initialValue.left) != null ? _d : 0); | ||
const [width, setWidth] = createSignal4((_e = initialValue.width) != null ? _e : 0); | ||
const [height, setHeight] = createSignal4((_f = initialValue.height) != null ? _f : 0); | ||
const isInside = createMemo2(() => x() >= 0 && y() >= 0 && x() <= width() && y() <= height()); | ||
const update = () => { | ||
const el = access2(element); | ||
if (!el) | ||
return; | ||
const relative = posRelativeToElement(pageX(), pageY(), el); | ||
batch2(() => { | ||
setX(relative.x); | ||
setY(relative.y); | ||
setTop(relative.top); | ||
setLeft(relative.left); | ||
setWidth(relative.width); | ||
setHeight(relative.height); | ||
}); | ||
}; | ||
access2(element) ? createComputed2(update) : onMount2(() => createComputed2(update)); | ||
return [ | ||
{ | ||
x, | ||
y, | ||
top, | ||
left, | ||
width, | ||
height, | ||
isInside | ||
}, | ||
update | ||
]; | ||
} | ||
import { | ||
createMousePosition, | ||
createPositionToElement, | ||
getPositionInElement, | ||
getPositionToElement, | ||
getPositionToScreen, | ||
makeMouseInsideListener, | ||
makeMousePositionListener, | ||
useMousePosition | ||
} from "./chunk-MOSNKDWK.js"; | ||
export { | ||
createMouseInElement, | ||
createMouseOnScreen, | ||
createMousePosition, | ||
createMouseToElement, | ||
posRelativeToElement, | ||
posRelativeToScreen | ||
createPositionToElement, | ||
getPositionInElement, | ||
getPositionToElement, | ||
getPositionToScreen, | ||
makeMouseInsideListener, | ||
makeMousePositionListener, | ||
useMousePosition | ||
}; |
{ | ||
"name": "@solid-primitives/mouse", | ||
"version": "1.2.0", | ||
"version": "2.0.0", | ||
"description": "A collection of Solid Primitives, that capture current mouse cursor position, and help to deal with common related usecases.", | ||
"author": "Damian Tarnawski @thetarnav <gthetarnav@gmail.com>", | ||
"author": "Damian Tarnawski <gthetarnav@gmail.com>", | ||
"license": "MIT", | ||
@@ -14,8 +14,6 @@ "homepage": "https://github.com/solidjs-community/solid-primitives/tree/main/packages/mouse#readme", | ||
"name": "mouse", | ||
"stage": 2, | ||
"stage": 3, | ||
"list": [ | ||
"createMousePosition", | ||
"createMouseToElement", | ||
"createMouseInElement", | ||
"createMouseOnScreen" | ||
"createPositionToElement" | ||
], | ||
@@ -27,5 +25,13 @@ "category": "Inputs" | ||
"type": "module", | ||
"main": "dist/index.cjs", | ||
"module": "dist/index.js", | ||
"types": "dist/index.d.ts", | ||
"main": "./dist/server.cjs", | ||
"module": "./dist/index.js", | ||
"types": "./dist/index.d.ts", | ||
"exports": { | ||
"node": { | ||
"import": "./dist/server.js", | ||
"require": "./dist/server.cjs" | ||
}, | ||
"import": "./dist/index.js", | ||
"require": "./dist/index.cjs" | ||
}, | ||
"files": [ | ||
@@ -35,5 +41,7 @@ "dist" | ||
"scripts": { | ||
"start": "vite -r ./dev/ -c ./dev/vite.config.ts", | ||
"start": "vite serve dev --host", | ||
"dev": "yarn start", | ||
"build": "tsup", | ||
"test": "uvu -r solid-register" | ||
"test": "uvu -r solid-register", | ||
"test:watch": "watchlist src test -- npm test" | ||
}, | ||
@@ -48,12 +56,13 @@ "keywords": [ | ||
"devDependencies": { | ||
"@solid-primitives/raf": "^1.0.5", | ||
"@solid-primitives/raf": "^2.1.0", | ||
"jsdom": "^19.0.0", | ||
"prettier": "^2.4.1", | ||
"solid-register": "^0.1.5", | ||
"tslib": "^2.3.1", | ||
"tsup": "^5.10.0", | ||
"unocss": "0.24.3", | ||
"uvu": "^0.5.2", | ||
"vite": "2.8.1", | ||
"vite-plugin-solid": "2.2.5" | ||
"prettier": "^2.6.2", | ||
"solid-register": "^0.2.3", | ||
"tslib": "^2.4.0", | ||
"tsup": "^5.12.6", | ||
"unocss": "0.31.13", | ||
"uvu": "^0.5.3", | ||
"vite": "2.9.5", | ||
"vite-plugin-solid": "2.2.6", | ||
"watchlist": "^0.3.1" | ||
}, | ||
@@ -64,6 +73,6 @@ "peerDependencies": { | ||
"dependencies": { | ||
"@solid-primitives/event-listener": "^1.6.0", | ||
"@solid-primitives/immutable": "^0.1.0", | ||
"@solid-primitives/utils": "^1.0.0" | ||
"@solid-primitives/event-listener": "^2.0.0", | ||
"@solid-primitives/rootless": "^1.1.0", | ||
"@solid-primitives/utils": "^1.2.0" | ||
} | ||
} |
264
README.md
@@ -10,11 +10,22 @@ <p> | ||
[![size](https://img.shields.io/npm/v/@solid-primitives/mouse?style=for-the-badge)](https://www.npmjs.com/package/@solid-primitives/mouse) | ||
[![stage](https://img.shields.io/endpoint?style=for-the-badge&url=https%3A%2F%2Fraw.githubusercontent.com%2Fsolidjs-community%2Fsolid-primitives%2Fmain%2Fassets%2Fbadges%2Fstage-2.json)](https://github.com/solidjs-community/solid-primitives#contribution-process) | ||
[![stage](https://img.shields.io/endpoint?style=for-the-badge&url=https%3A%2F%2Fraw.githubusercontent.com%2Fsolidjs-community%2Fsolid-primitives%2Fmain%2Fassets%2Fbadges%2Fstage-3.json)](https://github.com/solidjs-community/solid-primitives#contribution-process) | ||
A collection of primitives, capturing current mouse cursor position, and helping to deal with common usecases: | ||
- [`createMousePosition`](#createMousePosition) - Listens to the global mouse events, providing a reactive up-to-date position of the cursor on the page. | ||
- [`createMouseToElement`](#createMouseToElement) - Provides an auto-updating position relative to a provided element. It can be used with existing position signals or left to get the current cursor position itself. | ||
- [`createMouseInElement`](#createMouseInElement) - An alternative to `createMouseToElement`, that listens to mouse (and touch) events only inside the element. Provides information of position and if the element is being hovered. | ||
- [`createMouseOnScreen`](#createMouseOnScreen) - Answers the question: _Is the cursor on screen?_ | ||
##### Reactive primitives: | ||
- [`createMousePosition`](#createMousePosition) - Listens to the mouse events, providing a reactive up-to-date position of the cursor on the page. | ||
- [`createPositionToElement`](#createPositionToElement) - Provides an auto-updating position relative to a provided element. | ||
##### Non-reactive primitives: | ||
- [`makeMousePositionListener`](#makeMousePositionListener) - Attaches event listeners to provided targat, listeneing for changes to the mouse/touch position. | ||
- [`makeMouseInsideListener`](#makeMouseInsideListener) - Attaches event listeners to provided targat, listening for mouse/touch entering/leaving the element. | ||
##### Calculations: | ||
- [`getPositionToElement`](#getPositionToElement) - Turn position relative to the page, into position relative to an element. | ||
- [`getPositionInElement`](#getPositionInElement) - Turn position relative to the page, into position relative to an element. Clamped to the element bounds. | ||
- [`getPositionToScreen`](#getPositionToScreen) - Turn position relative to the page, into position relative to the screen. | ||
## Installation | ||
@@ -30,189 +41,138 @@ | ||
Listens to the global mouse events, providing a reactive up-to-date position of the cursor on the page. | ||
Attaches event listeners to provided targat, providing a reactive up-to-date position of the cursor on the page. | ||
### Usage | ||
#### Usage | ||
```ts | ||
```tsx | ||
import { createMousePosition } from "@solid-primitives/mouse"; | ||
const [{ x, y, sourceType }, clear] = createMousePosition({ touch: false }); | ||
// listening to touch events is enabled by default | ||
const pos = createMousePosition(window); | ||
createEffect(() => { | ||
console.log(pos.x, pos.y); | ||
}); | ||
// to clear all event listeners | ||
clear(); | ||
// target can be a reactive signal | ||
const [el, setEl] = createSignal(ref); | ||
const pos = createMousePosition(el); | ||
// if using a jsx ref, pass it as a function, or wrap primitive inside onMount | ||
let ref; | ||
const pos = createMousePosition(() => ref); | ||
<div ref={ref}></div>; | ||
``` | ||
### Types | ||
By default `createMousePosition` is listening to `touch` events as well. You can disable that behavior with `touch` and `followTouch` options. | ||
```ts | ||
function createMousePosition(options: MouseOptions = {}): [ | ||
getters: { | ||
x: Accessor<number>; | ||
y: Accessor<number>; | ||
sourceType: Accessor<MouseSourceType>; | ||
}, | ||
clear: VoidFunction | ||
]; | ||
interface MouseOptions { | ||
/** | ||
* Listen to `touchmove` events | ||
* @default true | ||
*/ | ||
touch?: boolean; | ||
/** | ||
* Initial values | ||
* @default { x:0, y:0 } | ||
*/ | ||
initialValue?: Position; | ||
/** | ||
* If enabled, position will be updated on touchmove event. | ||
* @default true | ||
*/ | ||
followTouch?: boolean; | ||
} | ||
interface Position { | ||
x: number; | ||
y: number; | ||
} | ||
type MouseSourceType = "mouse" | "touch" | null; | ||
// disables following touch position – only registers touch start | ||
const pos = createMousePosition(window, { followTouch: false }); | ||
// disables listeneing to any touch events | ||
const pos = createMousePosition(window, { touch: false }); | ||
``` | ||
## `createMouseToElement` | ||
#### `useMousePosition` | ||
Provides an autoupdating position relative to a provided element. It can be used with existing position signals, or left to get the current cursor position itself. | ||
This primitive providea a [shared root](https://github.com/solidjs-community/solid-primitives/tree/main/packages/rootless#createSharedRoot) variant that will listen to window mouse position, and reuse event listeners and signals across dependents. | ||
### Usage | ||
```ts | ||
import { createMouseToElement } from "@solid-primitives/mouse"; | ||
const [{ x, y, top, left, width, height, isInside }, manualUpdate] = createMouseToElement( | ||
() => myRef | ||
); | ||
// If position argument is left undefined, it will use | ||
// createMousePosition internally to track the cursor position. | ||
// But if you are already tracking the mouse position yourself, or with createMousePosition. | ||
// You can pass it to createMouseToElement to avoid additional performance payload. | ||
const [mouse] = createMousePosition(); | ||
const [{ x, y, isInside }] = createMouseToElement(el, mouse); | ||
// This also works when you are applying some transformations to the position, or debouncing it. | ||
const myPos = createMemo(() => { | ||
/* do sth with the mouse position */ | ||
const pos = useMousePosition(); | ||
createEffect(() => { | ||
console.log(pos.x, pos.y); | ||
}); | ||
const [{ x, y, isInside }] = createMouseToElement(el, myPos); | ||
``` | ||
### Types | ||
#### Definition | ||
```ts | ||
function createMouseToElement( | ||
element: MaybeAccessor<Element>, | ||
pos?: Accessor<Position> | { x: MaybeAccessor<number>; y: MaybeAccessor<number> }, | ||
options: PositionToElementOptions = {} | ||
): [ | ||
getters: { | ||
x: Accessor<number>; | ||
y: Accessor<number>; | ||
top: Accessor<number>; | ||
left: Accessor<number>; | ||
width: Accessor<number>; | ||
height: Accessor<number>; | ||
isInside: Accessor<boolean>; | ||
}, | ||
update: VoidFunction | ||
]; | ||
interface Position { | ||
x: number; | ||
y: number; | ||
} | ||
interface PositionToElementOptions extends MouseOptions { | ||
initialValue?: { | ||
top?: number; | ||
left?: number; | ||
width?: number; | ||
height?: number; | ||
x?: number; | ||
y?: number; | ||
}; | ||
} | ||
function createMousePosition( | ||
target?: MaybeAccessor<Window | Document | HTMLElement>, | ||
options?: MousePositionOptions | ||
): MousePositionInside; | ||
``` | ||
## `createMouseInElement` | ||
## `createPositionToElement` | ||
An alternative to [`createMouseToElement`](#createMouseToElement), that listens to mouse _(and touch)_ events only inside the element. Provides information of position and if is the element being currently hovered. | ||
Provides an autoupdating position relative to an element based on provided page position. | ||
### Usage | ||
#### Usage | ||
```ts | ||
import { createMouseInElement } from "@solid-primitives/mouse"; | ||
import { createPositionToElement, useMousePosition } from "@solid-primitives/mouse"; | ||
const [{ x, y, sourceType, isInside }, clear] = createMouseInElement(() => myRef, { | ||
followTouch: false | ||
const pos = useMousePosition(); | ||
const relative = createPositionToElement(ref, () => pos); | ||
createEffect(() => { | ||
console.log(relative.x, relative.y); | ||
}); | ||
// Same way as createMousePosition: | ||
// the "touch", and "foullowTouch" settings are enabled by default | ||
// to clear all event listeners | ||
clear(); | ||
// target can be a reactive signal | ||
const [el, setEl] = createSignal(ref); | ||
const relative = createPositionToElement(el, () => pos); | ||
// if using a jsx ref, pass it as a function, or wrap primitive inside onMount | ||
let ref; | ||
const relative = createPositionToElement(() => ref); | ||
<div ref={ref}></div>; | ||
``` | ||
### Types | ||
#### Definition | ||
```ts | ||
function createMouseInElement( | ||
element: MaybeAccessor<HTMLElement>, | ||
options: MouseOptions = {} | ||
): [ | ||
getters: { | ||
x: Accessor<number>; | ||
y: Accessor<number>; | ||
sourceType: Accessor<MouseSourceType>; | ||
isInside: Accessor<boolean>; | ||
}, | ||
clear: VoidFunction | ||
]; | ||
type MouseSourceType = "mouse" | "touch" | null; | ||
function createPositionToElement( | ||
element: Element | Accessor<Element | undefined>, | ||
pos: Accessor<Position>, | ||
options?: PositionToElementOptions | ||
): PositionRelativeToElement; | ||
``` | ||
## `createMouseOnScreen` | ||
## Non-reactive primitives: | ||
Answers the question: _Is the cursor on screen?_ | ||
### `makeMousePositionListener` | ||
### Usage | ||
Attaches event listeners to provided targat, listeneing for changes to the mouse/touch position. | ||
```ts | ||
import { createMouseOnScreen } from "@solid-primitives/mouse"; | ||
const clear = makeMousePositionListener(el, pos => console.log(pos), { touch: false }); | ||
// remove listeners manually (will happen on cleanup) | ||
clear(); | ||
``` | ||
const [isMouseOnScreen, clear] = createMouseOnScreen(true); | ||
### `makeMouseInsideListener` | ||
// to clear all event listeners | ||
Attaches event listeners to provided targat, listening for mouse/touch entering/leaving the element. | ||
```ts | ||
const clear = makeMouseInsideListener(el, inside => console.log(inside), { touch: false }); | ||
// remove listeners manually (will happen on cleanup) | ||
clear(); | ||
``` | ||
### Types | ||
## Calculations | ||
### `getPositionToElement` | ||
Turn position relative to the page, into position relative to an element. | ||
```ts | ||
function createMouseOnScreen( | ||
initialValue?: boolean | ||
): [onScreen: Accessor<boolean>, clear: VoidFunction]; | ||
function createMouseOnScreen( | ||
options?: MouseOnScreenOptions | ||
): [onScreen: Accessor<boolean>, clear: VoidFunction]; | ||
const pos = getPositionToElement(pageX, pageY, element); | ||
``` | ||
interface MouseOnScreenOptions { | ||
/** | ||
* Listen to touch events | ||
* @default true | ||
*/ | ||
touch?: boolean; | ||
/** | ||
* Initial value | ||
* @default false | ||
*/ | ||
initialValue?: boolean; | ||
} | ||
### `getPositionInElement` | ||
Turn position relative to the page, into position relative to an element. Clamped to the element bounds. | ||
```ts | ||
const pos = getPositionInElement(pageX, pageY, element); | ||
``` | ||
### `getPositionToScreen` | ||
Turn position relative to the page, into position relative to the screen. | ||
```ts | ||
const pos = getPositionToScreen(pageX, pageY); | ||
``` | ||
## Demo | ||
@@ -239,2 +199,18 @@ | ||
2.0.0 - **stage-3** | ||
[PR#113](https://github.com/solidjs-community/solid-primitives/pull/113) | ||
Removed `createMouseInElement`, `createMouseOnScreen` | ||
Renamed: | ||
- `posRelativeToElement` -> `getPositionToElement` | ||
- `posRelativeToScreen` -> `getPositionToScreen` | ||
- `createMouseToElement` -> `createPositionToElement` | ||
Added `makeMousePositionListener`, `makeMouseInsideListener` and `getPositionInElement` | ||
Removed clear() and update() functions from reactive primitives. `createPositionToElement` now only takes accessor position. | ||
</details> |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
31948
9
591
11
214
1
+ Added@solid-primitives/event-listener@2.4.0(transitive)
+ Added@solid-primitives/rootless@1.5.0(transitive)
- Removed@solid-primitives/immutable@^0.1.0
- Removed@solid-primitives/event-listener@1.6.1(transitive)
- Removed@solid-primitives/immutable@0.1.10(transitive)
- Removed@solid-primitives/rootless@0.1.0(transitive)