Skip to content

Instantly share code, notes, and snippets.

@mary-ext
Created January 22, 2025 09:09
Show Gist options
  • Select an option

  • Save mary-ext/8a9f3d11b3bcc84e22e6d09370664973 to your computer and use it in GitHub Desktop.

Select an option

Save mary-ext/8a9f3d11b3bcc84e22e6d09370664973 to your computer and use it in GitHub Desktop.
Solid.js useResizeObserver
import { batch, onCleanup } from 'solid-js';
export type ResizeCallback = (entry: ResizeObserverEntry) => void;
interface ObserverStorage {
l: ResizeObserverEntry | undefined;
c: ResizeCallback | ResizeCallback[];
}
const sym = Symbol('resize-observers');
type Target = { [sym]?: ObserverStorage };
const observer = new ResizeObserver((entries) => {
batch(() => {
for (let i = 0, ilen = entries.length; i < ilen; i++) {
const entry = entries[i];
const target = entry.target;
const storage = (target as Target)[sym];
if (storage === undefined) {
observer.unobserve(target);
continue;
}
const callback = storage.c;
storage.l = entry;
if (typeof callback === 'function') {
callback(entry);
} else {
for (let j = 0, jlen = callback.length; j < jlen; j++) {
(0, callback[j])(entry);
}
}
}
});
});
export const useResizeObserver = (node: HTMLElement, callback: ResizeCallback) => {
const t = node as Target;
let d = t[sym];
if (d === undefined) {
d = t[sym] = { c: callback, l: undefined };
} else {
const last = d.l;
const existing = d.c;
if (last !== undefined) {
batch(() => callback(last));
}
d.c = Array.isArray(existing) ? existing.concat(callback) : [existing, callback];
}
observer.observe(node);
onCleanup(() => {
const current = d.c;
if (current === callback) {
observer.unobserve(node);
t[sym] = undefined;
} else if (Array.isArray(current)) {
const index = current.indexOf(callback);
if (index === -1) {
return;
}
d.c = current.length === 2 ? current[index ^ 1] : current.toSpliced(index, 1);
}
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment