mirror of https://github.com/sveltejs/svelte
feat: add support for resize observer bindings (#8022)
Implements ResizeObserver bindings: #5524 (comment) Continuation of: #5963 Related to #7583 --------- Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>pull/8022/merge
parent
3a7685fef5
commit
0adc09da97
@ -0,0 +1,67 @@
|
|||||||
|
/**
|
||||||
|
* Resize observer singleton.
|
||||||
|
* One listener per element only!
|
||||||
|
* https://groups.google.com/a/chromium.org/g/blink-dev/c/z6ienONUb5A/m/F5-VcUZtBAAJ
|
||||||
|
*/
|
||||||
|
export class ResizeObserverSingleton {
|
||||||
|
constructor(readonly options?: ResizeObserverOptions) {}
|
||||||
|
|
||||||
|
observe(element: Element, listener: Listener) {
|
||||||
|
this._listeners.set(element, listener);
|
||||||
|
this._getObserver().observe(element, this.options);
|
||||||
|
return () => {
|
||||||
|
this._listeners.delete(element);
|
||||||
|
this._observer.unobserve(element); // this line can probably be removed
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static readonly entries: WeakMap<Element, ResizeObserverEntry> = 'WeakMap' in globalThis ? new WeakMap() : undefined;
|
||||||
|
|
||||||
|
private readonly _listeners: WeakMap<Element, Listener> = 'WeakMap' in globalThis ? new WeakMap() : undefined;
|
||||||
|
private _observer?: ResizeObserver;
|
||||||
|
private _getObserver() {
|
||||||
|
return this._observer ?? (this._observer = new ResizeObserver((entries) => {
|
||||||
|
for (const entry of entries) {
|
||||||
|
ResizeObserverSingleton.entries.set(entry.target, entry);
|
||||||
|
this._listeners.get(entry.target)?.(entry);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Listener = (entry: ResizeObserverEntry)=>any;
|
||||||
|
|
||||||
|
// TODO: Remove this
|
||||||
|
interface ResizeObserverSize {
|
||||||
|
readonly blockSize: number;
|
||||||
|
readonly inlineSize: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ResizeObserverEntry {
|
||||||
|
readonly borderBoxSize: readonly ResizeObserverSize[];
|
||||||
|
readonly contentBoxSize: readonly ResizeObserverSize[];
|
||||||
|
readonly contentRect: DOMRectReadOnly;
|
||||||
|
readonly devicePixelContentBoxSize: readonly ResizeObserverSize[];
|
||||||
|
readonly target: Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResizeObserverBoxOptions = 'border-box' | 'content-box' | 'device-pixel-content-box';
|
||||||
|
|
||||||
|
interface ResizeObserverOptions {
|
||||||
|
box?: ResizeObserverBoxOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ResizeObserver {
|
||||||
|
disconnect(): void;
|
||||||
|
observe(target: Element, options?: ResizeObserverOptions): void;
|
||||||
|
unobserve(target: Element): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ResizeObserverCallback {
|
||||||
|
(entries: ResizeObserverEntry[], observer: ResizeObserver): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare let ResizeObserver: {
|
||||||
|
prototype: ResizeObserver;
|
||||||
|
new(callback: ResizeObserverCallback): ResizeObserver;
|
||||||
|
};
|
Loading…
Reference in new issue