UNPKG

element-vir

Version:

Heroic. Reactive. Declarative. Type safe. Web components without compromise.

69 lines (68 loc) 2.33 kB
import { directive, Directive } from '../../lit-exports/all-lit-exports.js'; import { assertIsElementPartInfo } from './directive-helpers.js'; const directiveName = 'onResize'; /** * A directive that fires its listener any time the element that it's attached to is resized. This * uses the [built-in `ResizeObserver` * API](https://developer.mozilla.org/docs/Web/API/ResizeObserver), so it is very efficient. * * @category Directives * @example * * ```ts * import {html, defineElement, onResize} from 'element-vir'; * * const MyElement = defineElement()({ * tagName: 'my-element', * render() { * return html` * <div * ${onResize((size, element) => { * console.log('resized!', element, size); * })} * > * Some div * </div> * `; * }, * }); * ``` */ export const onResize = directive(class extends Directive { element; resizeObserver = new ResizeObserver((entries) => this.fireCallback(entries)); callback; constructor(partInfo) { super(partInfo); assertIsElementPartInfo(partInfo, directiveName); } fireCallback(entries) { const resizeEntry = entries[0]; if (!resizeEntry) { console.error(entries); throw new Error(`${directiveName} observation triggered but the first entry was empty.`); } void this.callback?.({ target: resizeEntry.target, contentRect: resizeEntry.contentRect }, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.element); } update(partInfo, [callback]) { assertIsElementPartInfo(partInfo, directiveName); this.callback = callback; const newElement = partInfo.element; const oldElement = this.element; // if the element changes we need to observe the new one if (newElement !== oldElement) { this.element = newElement; if (oldElement) { this.resizeObserver.unobserve(oldElement); } this.resizeObserver.observe(newElement); } return this.render(callback); } // eslint-disable-next-line @typescript-eslint/no-unused-vars render(callback) { return undefined; } });