UNPKG

@figliolia/size-observer

Version:
100 lines (99 loc) 2.72 kB
/** * Size Observer * * A light-weight wrapper around the native Resize Observer API * * ```typescript * import { SizeObserver } from "@figliolia/size-observer"; * * const node = document.getElementByID("myDOMNode"); * const observer = new SizeObserver(node, { * width: true, * height: true, * onChange: ({ height, width }) => {} * }); * * // Clean up * observer.destroy(); * ``` */ export class SizeObserver { node; width = 0; height = 0; options; observer; constructor(node, options) { if (!node) { throw new Error("Element Observer: node reference is undefined"); } this.node = node; this.options = options; this.initialize(); } setOptions(options) { let reconnect = false; if (this.options.type !== options.type) { reconnect = true; } this.options = options; if (reconnect) { this.destroy(); this.initialize(); } } initialize() { this.initializeLayout(); this.observer = new ResizeObserver(entries => { let emit = false; for (const entry of entries) { if (this.options.type === "content-box") { emit = this.parseBlock(entry.contentBoxSize); } else if (this.options.type === "device-pixel-content-box") { emit = this.parseBlock(entry.devicePixelContentBoxSize); } else { emit = this.parseBlock(entry.borderBoxSize); } } if (emit) { this.emit(); } }); this.observer.observe(this.node, { box: this.options.type ?? "border-box", }); } destroy() { this.observer.disconnect(); } initializeLayout() { const { height, width } = this.node.getBoundingClientRect(); this.width = width; this.height = height; this.emit(); } parseBlock(entry) { let emit = false; const { height, width } = this.options; for (const block of entry) { if (block.blockSize !== this.height) { this.height = block.blockSize; if (height) { emit = true; } } if (block.inlineSize !== this.width) { this.width = block.inlineSize; if (width) { emit = true; } } } return emit; } emit() { this.options.onChange({ width: this.width, height: this.height }, this.node); } }