@solid-primitives/bounds
Advanced tools
Comparing version 0.0.123 to 0.1.0
@@ -1,5 +0,4 @@ | ||
import { FalsyValue } from '@solid-primitives/utils'; | ||
import { Accessor } from 'solid-js'; | ||
type Bounds = { | ||
import { FalsyValue } from "@solid-primitives/utils"; | ||
import { Accessor } from "solid-js"; | ||
export type Bounds = { | ||
top: number; | ||
@@ -12,5 +11,5 @@ left: number; | ||
}; | ||
type NullableBounds = Record<keyof Bounds, number | null>; | ||
type UpdateGuard = <Args extends unknown[]>(update: (...args: Args) => void) => (...args: Args) => void; | ||
type Options = { | ||
export type NullableBounds = Record<keyof Bounds, number | null>; | ||
export type UpdateGuard = <Args extends unknown[]>(update: (...args: Args) => void) => (...args: Args) => void; | ||
export type Options = { | ||
trackScroll?: boolean | UpdateGuard; | ||
@@ -23,4 +22,4 @@ trackMutation?: boolean | UpdateGuard; | ||
*/ | ||
declare function getElementBounds(element: Element): Bounds; | ||
declare function getElementBounds(element: Element | FalsyValue): NullableBounds; | ||
export declare function getElementBounds(element: Element): Bounds; | ||
export declare function getElementBounds(element: Element | FalsyValue): NullableBounds; | ||
/** | ||
@@ -52,4 +51,2 @@ * Creates a reactive store-like object of current element bounds — position on the screen, and size dimensions. Bounds will be automatically updated on scroll, resize events and updates to the dom. | ||
*/ | ||
declare function createElementBounds(target: Accessor<Element | FalsyValue> | Element, { trackMutation, trackResize, trackScroll }?: Options): Readonly<NullableBounds>; | ||
export { type Bounds, type NullableBounds, type Options, type UpdateGuard, createElementBounds, getElementBounds }; | ||
export declare function createElementBounds(target: Accessor<Element | FalsyValue> | Element, { trackMutation, trackResize, trackScroll }?: Options): Readonly<NullableBounds>; |
@@ -1,80 +0,100 @@ | ||
import { makeEventListener } from '@solid-primitives/event-listener'; | ||
import { createResizeObserver } from '@solid-primitives/resize-observer'; | ||
import { createDerivedStaticStore } from '@solid-primitives/static-store'; | ||
import { access } from '@solid-primitives/utils'; | ||
import { createSignal, sharedConfig, onMount, onCleanup } from 'solid-js'; | ||
import { isServer } from 'solid-js/web'; | ||
// src/index.ts | ||
var NULLED_BOUNDS = { | ||
top: null, | ||
left: null, | ||
bottom: null, | ||
right: null, | ||
width: null, | ||
height: null | ||
import { makeEventListener } from "@solid-primitives/event-listener"; | ||
import { createResizeObserver } from "@solid-primitives/resize-observer"; | ||
import { createDerivedStaticStore } from "@solid-primitives/static-store"; | ||
import { access } from "@solid-primitives/utils"; | ||
import { createSignal, onCleanup, onMount, sharedConfig } from "solid-js"; | ||
import { isServer } from "solid-js/web"; | ||
const NULLED_BOUNDS = { | ||
top: null, | ||
left: null, | ||
bottom: null, | ||
right: null, | ||
width: null, | ||
height: null, | ||
}; | ||
function getElementBounds(element) { | ||
if (isServer || !element) { | ||
return { ...NULLED_BOUNDS }; | ||
} | ||
const rect = element.getBoundingClientRect(); | ||
return { | ||
top: rect.top, | ||
left: rect.left, | ||
bottom: rect.bottom, | ||
right: rect.right, | ||
width: rect.width, | ||
height: rect.height | ||
}; | ||
export function getElementBounds(element) { | ||
if (isServer || !element) { | ||
return { ...NULLED_BOUNDS }; | ||
} | ||
const rect = element.getBoundingClientRect(); | ||
return { | ||
top: rect.top, | ||
left: rect.left, | ||
bottom: rect.bottom, | ||
right: rect.right, | ||
width: rect.width, | ||
height: rect.height, | ||
}; | ||
} | ||
function createElementBounds(target, { trackMutation = true, trackResize = true, trackScroll = true } = {}) { | ||
if (isServer) { | ||
return NULLED_BOUNDS; | ||
} | ||
const isFn = typeof target === "function", [track, trigger] = createSignal(void 0, { equals: false }); | ||
let calc; | ||
if (sharedConfig.context) { | ||
calc = () => NULLED_BOUNDS; | ||
onMount(() => { | ||
calc = () => getElementBounds(access(target)); | ||
trigger(); | ||
}); | ||
} else if (isFn) { | ||
calc = () => getElementBounds(target()); | ||
onMount(trigger); | ||
} else calc = () => getElementBounds(target); | ||
const bounds = createDerivedStaticStore(() => (track(), calc())); | ||
if (trackResize) { | ||
createResizeObserver( | ||
isFn ? () => target() || [] : target, | ||
typeof trackResize === "function" ? trackResize(trigger) : trigger | ||
); | ||
} | ||
if (trackScroll) { | ||
const scrollHandler = isFn ? (e) => { | ||
const el = target(); | ||
el && e.target instanceof Node && e.target.contains(el) && trigger(); | ||
} : (e) => e.target instanceof Node && e.target.contains(target) && trigger(); | ||
makeEventListener( | ||
window, | ||
"scroll", | ||
typeof trackScroll === "function" ? trackScroll(scrollHandler) : scrollHandler, | ||
{ capture: true } | ||
); | ||
} | ||
if (trackMutation) { | ||
const mo = new MutationObserver( | ||
typeof trackMutation === "function" ? trackMutation(trigger) : trigger | ||
); | ||
mo.observe(document.body, { | ||
attributeFilter: ["style", "class"], | ||
subtree: true, | ||
childList: true | ||
}); | ||
onCleanup(() => mo.disconnect()); | ||
} | ||
return bounds; | ||
/** | ||
* Creates a reactive store-like object of current element bounds — position on the screen, and size dimensions. Bounds will be automatically updated on scroll, resize events and updates to the dom. | ||
* | ||
* @param target Element for calculating bounds. Can be a reactive signal. Set to falsy value to disable tracking. | ||
* @param options Choose which events should be tracked *(All are enabled by default)* | ||
* - `options.trackScroll` — listen to window scroll events | ||
* - `options.trackMutation` — listen to changes to the dom structure/styles | ||
* - `options.trackResize` — listen to element's resize events | ||
* @returns reactive object of {@link target} bounds | ||
* @example | ||
* ```ts | ||
* const target = document.querySelector("#my_elem")!; | ||
* const bounds = createElementBounds(target); | ||
* | ||
* createEffect(() => { | ||
* console.log( | ||
* bounds.width, // => number | ||
* bounds.height, // => number | ||
* bounds.top, // => number | ||
* bounds.left, // => number | ||
* bounds.right, // => number | ||
* bounds.bottom, // => number | ||
* ); | ||
* }); | ||
* ``` | ||
*/ | ||
export function createElementBounds(target, { trackMutation = true, trackResize = true, trackScroll = true } = {}) { | ||
if (isServer) { | ||
return NULLED_BOUNDS; | ||
} | ||
const isFn = typeof target === "function", [track, trigger] = createSignal(void 0, { equals: false }); | ||
let calc; | ||
// during hydration we need to make sure the initial state is the same as the server | ||
if (sharedConfig.context) { | ||
calc = () => NULLED_BOUNDS; | ||
onMount(() => { | ||
calc = () => getElementBounds(access(target)); | ||
trigger(); | ||
}); | ||
} | ||
// a function target might be a jsx ref, so it may not be reactive - retrigger manually on mount | ||
else if (isFn) { | ||
calc = () => getElementBounds(target()); | ||
onMount(trigger); | ||
} | ||
// otherwise we can just use the target directly - it will never change | ||
else | ||
calc = () => getElementBounds(target); | ||
const bounds = createDerivedStaticStore(() => (track(), calc())); | ||
if (trackResize) { | ||
createResizeObserver(isFn ? () => target() || [] : target, typeof trackResize === "function" ? trackResize(trigger) : trigger); | ||
} | ||
if (trackScroll) { | ||
const scrollHandler = isFn | ||
? (e) => { | ||
const el = target(); | ||
el && e.target instanceof Node && e.target.contains(el) && trigger(); | ||
} | ||
: (e) => e.target instanceof Node && e.target.contains(target) && trigger(); | ||
makeEventListener(window, "scroll", typeof trackScroll === "function" ? trackScroll(scrollHandler) : scrollHandler, { capture: true }); | ||
} | ||
if (trackMutation) { | ||
const mo = new MutationObserver(typeof trackMutation === "function" ? trackMutation(trigger) : trigger); | ||
mo.observe(document.body, { | ||
attributeFilter: ["style", "class"], | ||
subtree: true, | ||
childList: true, | ||
}); | ||
onCleanup(() => mo.disconnect()); | ||
} | ||
return bounds; | ||
} | ||
export { createElementBounds, getElementBounds }; |
{ | ||
"name": "@solid-primitives/bounds", | ||
"version": "0.0.123", | ||
"version": "0.1.0", | ||
"description": "Primitives for tracking HTML element size and position on screen as it changes.", | ||
@@ -37,3 +37,2 @@ "author": "Damian Tarnawski <gthetarnav@gmail.com>", | ||
"type": "module", | ||
"main": "./dist/index.cjs", | ||
"module": "./dist/index.js", | ||
@@ -47,6 +46,2 @@ "types": "./dist/index.d.ts", | ||
"default": "./dist/index.js" | ||
}, | ||
"require": { | ||
"types": "./dist/index.d.cts", | ||
"default": "./dist/index.cjs" | ||
} | ||
@@ -56,9 +51,9 @@ }, | ||
"solid-js": "^1.8.7", | ||
"@solid-primitives/scheduled": "^1.4.4" | ||
"@solid-primitives/scheduled": "^1.5.0" | ||
}, | ||
"dependencies": { | ||
"@solid-primitives/event-listener": "^2.3.3", | ||
"@solid-primitives/resize-observer": "^2.0.27", | ||
"@solid-primitives/static-store": "^0.0.9", | ||
"@solid-primitives/utils": "^6.2.3" | ||
"@solid-primitives/event-listener": "^2.4.0", | ||
"@solid-primitives/resize-observer": "^2.1.0", | ||
"@solid-primitives/static-store": "^0.1.0", | ||
"@solid-primitives/utils": "^6.3.0" | ||
}, | ||
@@ -65,0 +60,0 @@ "peerDependencies": { |
@@ -7,3 +7,2 @@ <p> | ||
[![turborepo](https://img.shields.io/badge/built%20with-turborepo-cc00ff.svg?style=for-the-badge&logo=turborepo)](https://turborepo.org/) | ||
[![size](https://img.shields.io/bundlephobia/minzip/@solid-primitives/bounds?style=for-the-badge&label=size)](https://bundlephobia.com/package/@solid-primitives/bounds) | ||
@@ -10,0 +9,0 @@ [![version](https://img.shields.io/npm/v/@solid-primitives/bounds?style=for-the-badge)](https://www.npmjs.com/package/@solid-primitives/bounds) |
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
12277
5
149
105
1
- Removed@solid-primitives/static-store@0.0.9(transitive)