UNPKG

@tabula/use-size

Version:

Watches the DOM element's size with ResizeObserver

8 lines (7 loc) 5.35 kB
{ "version": 3, "sources": ["../src/useSize.ts", "../src/observe.ts", "../src/size.ts"], "sourcesContent": ["import { RefCallback, useCallback, useLayoutEffect, useState } from 'react';\n\nimport { Listener, observe } from './observe';\nimport { Size, updateSizeFromRect } from './size';\n\ntype Result<E> = [RefCallback<E>, Size, E | null];\n\nconst defaultSize: Size = {\n width: 0,\n height: 0,\n};\n\nexport function useSize<E extends Element = Element>(initialSize: Size = defaultSize): Result<E> {\n const [target, setTarget] = useState<E | null>(null);\n const [size, setSize] = useState(initialSize);\n\n const handleRect = useCallback<Listener>((next) => {\n setSize((current) => updateSizeFromRect(current, next));\n }, []);\n\n useLayoutEffect(() => {\n if (target == null) {\n return;\n }\n\n handleRect(target.getBoundingClientRect());\n\n let didUnsubscribe = false;\n\n const handleResize = (rect: DOMRect) => {\n if (didUnsubscribe) {\n return;\n }\n\n handleRect(rect);\n };\n\n const unsubscribe = observe(target, handleResize);\n\n return () => {\n didUnsubscribe = true;\n\n unsubscribe();\n };\n }, [target, handleRect]);\n\n return [setTarget, size, target];\n}\n", "export type Listener = (rect: DOMRect) => void;\n\n// region Listeners\n\nconst allListeners = new WeakMap<Element, Listener[]>();\n\nlet isTicking = false;\n\nconst queue = new Map<Element, DOMRect>();\n\nfunction flushQueue() {\n for (const [target, rect] of queue.entries()) {\n const listeners = allListeners.get(target);\n\n if (listeners == null) {\n continue;\n }\n\n for (const listener of listeners) {\n listener(rect);\n }\n }\n\n queue.clear();\n\n isTicking = false;\n}\n\nfunction onResize(entries: ResizeObserverEntry[]) {\n for (const entry of entries) {\n queue.set(entry.target, entry.contentRect);\n }\n\n if (!isTicking) {\n requestAnimationFrame(flushQueue);\n }\n\n isTicking = true;\n}\n\n// endregion\n\n// region Observer\n\nlet observer: ResizeObserver | null = null;\n\nfunction getObserver(): ResizeObserver {\n observer ??= new ResizeObserver(onResize);\n\n return observer;\n}\n\n// endregion\n\n// region Observe\n\nfunction unobserve(target: Element, listener: Listener) {\n const listeners = allListeners.get(target) ?? [];\n\n if (listeners.length === 1) {\n getObserver().unobserve(target);\n\n allListeners.delete(target);\n\n return;\n }\n\n const nextListeners = listeners.filter((it) => it === listener);\n\n allListeners.set(target, nextListeners);\n}\n\nexport function observe(target: Element, listener: Listener): () => void {\n getObserver().observe(target);\n\n const listeners = allListeners.get(target) ?? [];\n\n listeners.push(listener);\n\n allListeners.set(target, listeners);\n\n return () => {\n unobserve(target, listener);\n };\n}\n\n// endregion\n", "export type Size = {\n height: number;\n width: number;\n};\n\nfunction rectToSize({ height, width }: DOMRect) {\n return {\n height: Math.round(height),\n width: Math.round(width),\n };\n}\n\nfunction areEqual(left: Size, right: Size) {\n return left.height === right.height && left.width === right.width;\n}\n\nexport function updateSizeFromRect(current: Size, rect: DOMRect): Size {\n const next = rectToSize(rect);\n\n return areEqual(current, next) ? current : next;\n}\n"], "mappings": ";AAAA,SAAsB,aAAa,iBAAiB,gBAAgB;;;ACIpE,IAAM,eAAe,oBAAI,QAA6B;AAEtD,IAAI,YAAY;AAEhB,IAAM,QAAQ,oBAAI,IAAsB;AAExC,SAAS,aAAa;AACpB,aAAW,CAAC,QAAQ,IAAI,KAAK,MAAM,QAAQ,GAAG;AAC5C,UAAM,YAAY,aAAa,IAAI,MAAM;AAEzC,QAAI,aAAa,MAAM;AACrB;AAAA,IACF;AAEA,eAAW,YAAY,WAAW;AAChC,eAAS,IAAI;AAAA,IACf;AAAA,EACF;AAEA,QAAM,MAAM;AAEZ,cAAY;AACd;AAEA,SAAS,SAAS,SAAgC;AAChD,aAAW,SAAS,SAAS;AAC3B,UAAM,IAAI,MAAM,QAAQ,MAAM,WAAW;AAAA,EAC3C;AAEA,MAAI,CAAC,WAAW;AACd,0BAAsB,UAAU;AAAA,EAClC;AAEA,cAAY;AACd;AAMA,IAAI,WAAkC;AAEtC,SAAS,cAA8B;AACrC,eAAa,IAAI,eAAe,QAAQ;AAExC,SAAO;AACT;AAMA,SAAS,UAAU,QAAiB,UAAoB;AACtD,QAAM,YAAY,aAAa,IAAI,MAAM,KAAK,CAAC;AAE/C,MAAI,UAAU,WAAW,GAAG;AAC1B,gBAAY,EAAE,UAAU,MAAM;AAE9B,iBAAa,OAAO,MAAM;AAE1B;AAAA,EACF;AAEA,QAAM,gBAAgB,UAAU,OAAO,CAAC,OAAO,OAAO,QAAQ;AAE9D,eAAa,IAAI,QAAQ,aAAa;AACxC;AAEO,SAAS,QAAQ,QAAiB,UAAgC;AACvE,cAAY,EAAE,QAAQ,MAAM;AAE5B,QAAM,YAAY,aAAa,IAAI,MAAM,KAAK,CAAC;AAE/C,YAAU,KAAK,QAAQ;AAEvB,eAAa,IAAI,QAAQ,SAAS;AAElC,SAAO,MAAM;AACX,cAAU,QAAQ,QAAQ;AAAA,EAC5B;AACF;;;AC/EA,SAAS,WAAW,EAAE,QAAQ,MAAM,GAAY;AAC9C,SAAO;AAAA,IACL,QAAQ,KAAK,MAAM,MAAM;AAAA,IACzB,OAAO,KAAK,MAAM,KAAK;AAAA,EACzB;AACF;AAEA,SAAS,SAAS,MAAY,OAAa;AACzC,SAAO,KAAK,WAAW,MAAM,UAAU,KAAK,UAAU,MAAM;AAC9D;AAEO,SAAS,mBAAmB,SAAe,MAAqB;AACrE,QAAM,OAAO,WAAW,IAAI;AAE5B,SAAO,SAAS,SAAS,IAAI,IAAI,UAAU;AAC7C;;;AFbA,IAAM,cAAoB;AAAA,EACxB,OAAO;AAAA,EACP,QAAQ;AACV;AAEO,SAAS,QAAqC,cAAoB,aAAwB;AAC/F,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAmB,IAAI;AACnD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,WAAW;AAE5C,QAAM,aAAa,YAAsB,CAAC,SAAS;AACjD,YAAQ,CAAC,YAAY,mBAAmB,SAAS,IAAI,CAAC;AAAA,EACxD,GAAG,CAAC,CAAC;AAEL,kBAAgB,MAAM;AACpB,QAAI,UAAU,MAAM;AAClB;AAAA,IACF;AAEA,eAAW,OAAO,sBAAsB,CAAC;AAEzC,QAAI,iBAAiB;AAErB,UAAM,eAAe,CAAC,SAAkB;AACtC,UAAI,gBAAgB;AAClB;AAAA,MACF;AAEA,iBAAW,IAAI;AAAA,IACjB;AAEA,UAAM,cAAc,QAAQ,QAAQ,YAAY;AAEhD,WAAO,MAAM;AACX,uBAAiB;AAEjB,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,QAAQ,UAAU,CAAC;AAEvB,SAAO,CAAC,WAAW,MAAM,MAAM;AACjC;", "names": [] }