UNPKG

svelte

Version:

Cybernetically enhanced web apps

109 lines (91 loc) 2.89 kB
import { effect, teardown } from '../../../reactivity/effects.js'; import { untrack } from '../../../runtime.js'; /** * Resize observer singleton. * One listener per element only! * https://groups.google.com/a/chromium.org/g/blink-dev/c/z6ienONUb5A/m/F5-VcUZtBAAJ */ class ResizeObserverSingleton { /** */ #listeners = new WeakMap(); /** @type {ResizeObserver | undefined} */ #observer; /** @type {ResizeObserverOptions} */ #options; /** @static */ static entries = new WeakMap(); /** @param {ResizeObserverOptions} options */ constructor(options) { this.#options = options; } /** * @param {Element} element * @param {(entry: ResizeObserverEntry) => any} listener */ observe(element, listener) { var listeners = this.#listeners.get(element) || new Set(); listeners.add(listener); this.#listeners.set(element, listeners); this.#getObserver().observe(element, this.#options); return () => { var listeners = this.#listeners.get(element); listeners.delete(listener); if (listeners.size === 0) { this.#listeners.delete(element); /** @type {ResizeObserver} */ (this.#observer).unobserve(element); } }; } #getObserver() { return ( this.#observer ?? (this.#observer = new ResizeObserver( /** @param {any} entries */ (entries) => { for (var entry of entries) { ResizeObserverSingleton.entries.set(entry.target, entry); for (var listener of this.#listeners.get(entry.target) || []) { listener(entry); } } } )) ); } } var resize_observer_content_box = /* @__PURE__ */ new ResizeObserverSingleton({ box: 'content-box' }); var resize_observer_border_box = /* @__PURE__ */ new ResizeObserverSingleton({ box: 'border-box' }); var resize_observer_device_pixel_content_box = /* @__PURE__ */ new ResizeObserverSingleton({ box: 'device-pixel-content-box' }); /** * @param {Element} element * @param {'contentRect' | 'contentBoxSize' | 'borderBoxSize' | 'devicePixelContentBoxSize'} type * @param {(entry: keyof ResizeObserverEntry) => void} set */ export function bind_resize_observer(element, type, set) { var observer = type === 'contentRect' || type === 'contentBoxSize' ? resize_observer_content_box : type === 'borderBoxSize' ? resize_observer_border_box : resize_observer_device_pixel_content_box; var unsub = observer.observe(element, /** @param {any} entry */ (entry) => set(entry[type])); teardown(unsub); } /** * @param {HTMLElement} element * @param {'clientWidth' | 'clientHeight' | 'offsetWidth' | 'offsetHeight'} type * @param {(size: number) => void} set */ export function bind_element_size(element, type, set) { var unsub = resize_observer_border_box.observe(element, () => set(element[type])); effect(() => { // The update could contain reads which should be ignored untrack(() => set(element[type])); return unsub; }); }