UNPKG

@smoovy/observer

Version:
176 lines (141 loc) 4.34 kB
# @smoovy/observer [![Version](https://flat.badgen.net/npm/v/@smoovy/observer)](https://www.npmjs.com/package/@smoovy/observer) ![Size](https://flat.badgen.net/bundlephobia/minzip/@smoovy/observer) Easily observe states of HTML elements and the viewport. ## Installation ```sh yarn add @smoovy/observer ``` or ```sh npm install --save @smoovy/observer ``` ## Why?! Operations like `window.innerWidth` and `element.offsetTop` will have an impact on the performance if not used properly. So this package is useful to avoid [layout thrashing](https://devhints.io/layout-thrashing) by batching all of the expensive calls together and only executing them if needed. ## Usage For most use cases using the exposed `observe` and `unobserve` methods is sufficient. ### Observing the window ```js import { observe } from '@smoovy/observer'; const observable = observe(window); const unlisten = observable.onChange(() => { console.log(`The viewport size is ${observable.width}x${observable.height}`); }); ``` To remove the listener and observable you can simply call the the `unobserve` method: ```js import { unobserve } from '@smoovy/observer'; // Remove update listener unlisten(); // Remove observable from detection unobserve(observable); ``` #### Throttling the update listener calls This will throttle the update callback to **100ms**: ```js import { throttle } from '@smoovy/utils/throttle'; const observable = observe(window).onChange( throttle(() => {}, 100) ); ``` #### Updating the observable manually ```js observable.update(); ``` #### When does a viewport update occur? The update callback is called everytime the user triggers the `resize` event on the `window` or through `ResizeObserver`s change detection. ### Observing an element Observing elements works through the same API as with the window. ```js import { observe } from '@smoovy/observer'; const element = document.querySelector('#test'); const observable = observe(element, { visibilityDetection: true, resizeDetection: true }); ``` #### Listening/Unlistening for element updates ```js const listener = observable.onChange(({ size, coord }) => { console.log('Element bounds:', size); console.log('Element page offset:', coord); }); // Stop listening listener(); ``` #### Updating the element state manually ```js observable.update(); ``` #### Removing the element state from the observer ```js import { unobserve } from '@smoovy/observer'; unobserve(observable); ``` #### Listening for visibility and dimension changes separately The `onChange` callback bundles the `onDimChnage` and `onVisChange` callback together. You can listen to either of those separately: ```js const listenerVis = observable.onVisChange(() => { console.log('Element is now', observable.visible); }); const listenerDim = observable.onDimChange(() => { console.log('Element has changed size', observable.size, observable.pos); }); ``` ### Further configurations ```js /** * The target to observe. Can be HTMLElement or Window */ target: HTMLElement | Window; /** * Use `getBoundingClientRect()` instead of offsetWidth etc. * * Default = false */ useBounds?: boolean; /** * Automatically listen for changes, resizes and updates once created * * Default = true */ autoAttach?: boolean; /** * Whether to use visibility detection via the IntersectionObserver API. * You can configure it with a custom threshold. * * Default = false */ visibilityDetection?: boolean | IntersectionObserverInit; /** * If `visiblityDetection` is enabled, this will delay the visibile * event by a defined number (ms) * * Default = 0 */ visibilityDelay?: number; /** * If `visibiltiyDetection` is enabled, remove the target from the * IntersectionObserver once it has been marked as visible * * Default = false */ detectVisibilityOnce?: boolean; /** * Whether to detect dimension changes via the ResizeObserver API * * Default = false */ resizeDetection?: boolean | ResizeObserverOptions; /** * Debounce is the number of milliseconds to wait for the next change. * So if the delta value is below this threshold the resize event will * be discarded and therefore the observable will not be updated. * * Default = 16.6 */ resizeDebounce?: number; ``` ## License See the [LICENSE](../../LICENSE) file for license rights and limitations (MIT).