@tamagui/use-element-layout 1.134.5 → 1.135.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +50 -31
- package/dist/cjs/index.js +72 -66
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/index.native.js +93 -81
- package/dist/cjs/index.native.js.map +3 -3
- package/dist/esm/index.js +73 -65
- package/dist/esm/index.js.map +2 -2
- package/dist/esm/index.mjs +49 -31
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +88 -69
- package/dist/esm/index.native.js.map +1 -1
- package/package.json +4 -4
- package/src/{index.ts → index.tsx} +125 -109
- package/types/index.d.ts +8 -1
- package/types/index.d.ts.map +3 -3
package/types/index.d.ts.map
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"mappings": "AAEA,
|
|
2
|
+
"mappings": "AAEA,cAAgD,gBAAgB,iBAAiB,OAAO;;;;AAgBxF,OAAO,cAAM,8BAA+B,EAC1C,SACA,UAID,EAHE;CACD;CACA,UAAU;AACX,MAAG;KAiBC,+BAA+B;CAClC;AACD;KAEI,4BAA4B,QAAQ,SAAS;AAIlD,OAAO,iBAAS,oBAAoBA,OAAO;AAI3C,YAAY,cAAc;CACxB;CACA;CACA;CACA;CACA;CACA;AACD;AAED,YAAY,cAAc;CACxB,aAAa;EACX,QAAQ;EACR;CACD;CACD;AACD;AASD,OAAO,iBAAS;AAgJhB,OAAO,cAAM,wBACXC,UAAU,iBACVC,YAAY,oBACX;AAiBH,OAAO,iBAAS,iBACdC,KAAK,UAAU,+BACfC,aAAaC,GAAG;AA2DlB,OAAO,cAAM,6BACXC,MAAM,uBACL,QAAQ,kBAAkB;AAiB7B,OAAO,cAAM,cACXC,MAAM,aACNC,aAAa,uBACZ,eAAe;KAcb,qBAAqBC,WAAWC,WAAWC,eAAeC;KAE1D,aACHH,WACAC,WACAC,eACAC,gBACAC,eACAC;AAGF,OAAO,cAAM,UACXP,MAAM,aACNQ,UAAU,cACT,QAAQ;AAWX,OAAO,iBAAS,cACdR,MAAM,eACJQ,UAAU,cAAc,QAAQ;KAI/B,eAAe;CAAE;CAAe;CAAe;CAAe;AAAgB;AAEnF,OAAO,cAAM,kBACXR,MAAM,aACNS,UAAU,sBACT,QAAQ;AAQX,OAAO,cAAM,wBACXT,MAAM,kBACHS,UAAU,sBAAsB,QAAQ;AAI7C,OAAO,cAAM,gBACXT,MAAM,aACNU,cAAc,aACdF,UAAU,cACT,QAAQ;AAQX,OAAO,iBAAS,oBACdR,MAAM,eACJW,YAAY,aAAaH,UAAU,cAAc,QAAQ",
|
|
3
3
|
"names": [
|
|
4
4
|
"state: LayoutMeasurementStrategy",
|
|
5
5
|
"nodeRect: DOMRectReadOnly",
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
"relativeTo: HTMLElement"
|
|
23
23
|
],
|
|
24
24
|
"sources": [
|
|
25
|
-
"src/index.
|
|
25
|
+
"src/index.tsx"
|
|
26
26
|
],
|
|
27
27
|
"sourcesContent": [
|
|
28
|
-
"import { isClient, useIsomorphicLayoutEffect } from '@tamagui/constants'\nimport { isEqualShallow } from '@tamagui/is-equal-shallow'\nimport { useCallback, type RefObject } from 'react'\n\nconst LayoutHandlers = new WeakMap<HTMLElement, Function>()\nconst Nodes = new Set<HTMLElement>()\nconst IntersectionState = new WeakMap<HTMLElement, boolean>()\n\n// Single persistent IntersectionObserver for all nodes\nlet globalIntersectionObserver: IntersectionObserver | null = null\n\ntype TamaguiComponentStatePartial = {\n host?: any\n}\n\ntype LayoutMeasurementStrategy = 'off' | 'sync' | 'async'\n\nlet strategy: LayoutMeasurementStrategy = 'async'\n\nexport function setOnLayoutStrategy(state: LayoutMeasurementStrategy): void {\n strategy = state\n}\n\nexport type LayoutValue = {\n x: number\n y: number\n width: number\n height: number\n pageX: number\n pageY: number\n}\n\nexport type LayoutEvent = {\n nativeEvent: {\n layout: LayoutValue\n target: any\n }\n timeStamp: number\n}\n\nconst NodeRectCache = new WeakMap<HTMLElement, DOMRect>()\nconst ParentRectCache = new WeakMap<HTMLElement, DOMRect>()\nconst LastChangeTime = new WeakMap<HTMLElement, number>()\n\nconst rAF = typeof window !== 'undefined' ? window.requestAnimationFrame : undefined\n\n// prevent thrashing during first hydration (somewhat, streaming gets trickier)\nlet avoidUpdates = true\nconst queuedUpdates = new Map<HTMLElement, Function>()\n\nexport function enable(): void {\n if (avoidUpdates) {\n avoidUpdates = false\n if (queuedUpdates) {\n queuedUpdates.forEach((cb) => cb())\n queuedUpdates.clear()\n }\n }\n}\n\nfunction startGlobalObservers() {\n if (!isClient || globalIntersectionObserver) return\n\n globalIntersectionObserver = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n const node = entry.target as HTMLElement\n if (IntersectionState.get(node) !== entry.isIntersecting) {\n IntersectionState.set(node, entry.isIntersecting)\n }\n })\n },\n {\n threshold: 0,\n }\n )\n}\n\nif (isClient) {\n if (rAF) {\n const supportsCheckVisibility = 'checkVisibility' in document.body\n\n const BoundingRects = new WeakMap<any, DOMRectReadOnly | undefined>()\n\n async function updateLayoutIfChanged(node: HTMLElement) {\n if (IntersectionState.get(node) === false) {\n // avoid due to not intersecting\n return\n }\n // triggers style recalculation in safari which is slower than not\n if (process.env.TAMAGUI_ONLAYOUT_VISIBILITY_CHECK === '1') {\n if (supportsCheckVisibility && !(node as any).checkVisibility()) {\n // avoid due to not visible\n return\n }\n }\n\n const onLayout = LayoutHandlers.get(node)\n if (typeof onLayout !== 'function') return\n\n const parentNode = node.parentElement\n if (!parentNode) return\n\n let nodeRect: DOMRectReadOnly\n let parentRect: DOMRectReadOnly\n\n if (strategy === 'async') {\n const [nr, pr] = await Promise.all([\n BoundingRects.get(node) || getBoundingClientRectAsync(node),\n BoundingRects.get(parentNode) || getBoundingClientRectAsync(parentNode),\n ])\n\n if (nr === false || pr === false) {\n return\n }\n\n nodeRect = nr\n parentRect = pr\n } else {\n nodeRect = node.getBoundingClientRect()\n parentRect = parentNode.getBoundingClientRect()\n }\n\n const cachedRect = NodeRectCache.get(node)\n const cachedParentRect = NodeRectCache.get(parentNode)\n\n if (\n !cachedRect ||\n // has changed one rect\n // @ts-expect-error DOMRectReadOnly can go into object\n (!isEqualShallow(cachedRect, nodeRect) &&\n // @ts-expect-error DOMRectReadOnly can go into object\n (!cachedParentRect || !isEqualShallow(cachedParentRect, parentRect)))\n ) {\n NodeRectCache.set(node, nodeRect)\n ParentRectCache.set(parentNode, parentRect)\n\n const event = getElementLayoutEvent(nodeRect, parentRect)\n\n if (avoidUpdates) {\n queuedUpdates.set(node, () => onLayout(event))\n } else {\n onLayout(event)\n }\n }\n }\n\n // note that getBoundingClientRect() does not thrash layout if its after an animation frame\n // ok new note: *if* it needed recalc then yea, but browsers often skip that, so it does\n // which is why we use async strategy in general\n rAF!(layoutOnAnimationFrame)\n\n // only run once in a few frames, this could be adjustable\n let frameCount = 0\n\n const userSkipVal = process.env.TAMAGUI_LAYOUT_FRAME_SKIP\n const RUN_EVERY_X_FRAMES = userSkipVal ? +userSkipVal : 10\n\n async function layoutOnAnimationFrame() {\n if (strategy !== 'off') {\n if (!Nodes.size || frameCount++ % RUN_EVERY_X_FRAMES !== 0) {\n // skip a few frames to avoid work\n rAF!(layoutOnAnimationFrame)\n return\n }\n\n if (frameCount === Number.MAX_SAFE_INTEGER) {\n frameCount = 0\n }\n\n // do a 1 rather than N IntersectionObservers for performance\n await new Promise<void>((res) => {\n const io = new IntersectionObserver(\n (entries) => {\n io.disconnect()\n for (const entry of entries) {\n BoundingRects.set(entry.target, entry.boundingClientRect)\n }\n res()\n },\n {\n threshold: 0,\n }\n )\n for (const node of Nodes) {\n if (node.parentElement instanceof HTMLElement) {\n io.observe(node)\n io.observe(node.parentElement)\n }\n }\n })\n\n Nodes.forEach((node) => {\n updateLayoutIfChanged(node)\n })\n }\n\n rAF!(layoutOnAnimationFrame)\n }\n } else {\n if (process.env.NODE_ENV === 'development') {\n console.warn(\n `No requestAnimationFrame - please polyfill for onLayout to work correctly`\n )\n }\n }\n}\n\nexport const getElementLayoutEvent = (\n nodeRect: DOMRectReadOnly,\n parentRect: DOMRectReadOnly\n): LayoutEvent => {\n return {\n nativeEvent: {\n layout: getRelativeDimensions(nodeRect, parentRect),\n target: nodeRect,\n },\n timeStamp: Date.now(),\n }\n}\n\nconst getRelativeDimensions = (a: DOMRectReadOnly, b: DOMRectReadOnly) => {\n const { height, left, top, width } = a\n const x = left - b.left\n const y = top - b.top\n return { x, y, width, height, pageX: a.left, pageY: a.top }\n}\n\nexport function useElementLayout(\n ref: RefObject<TamaguiComponentStatePartial>,\n onLayout?: ((e: LayoutEvent) => void) | null\n): void {\n // ensure always up to date so we can avoid re-running effect\n const node = ensureWebElement(ref.current?.host)\n if (node && onLayout) {\n LayoutHandlers.set(node, onLayout)\n }\n\n useIsomorphicLayoutEffect(() => {\n if (!onLayout) return\n const node = ref.current?.host\n if (!node) return\n\n Nodes.add(node)\n\n // Add node to intersection observer\n startGlobalObservers()\n if (globalIntersectionObserver) {\n globalIntersectionObserver.observe(node)\n // Initialize as intersecting by default\n IntersectionState.set(node, true)\n }\n\n // always do one immediate sync layout event no matter the strategy for accuracy\n const parentNode = node.parentNode\n if (parentNode) {\n onLayout(\n getElementLayoutEvent(\n node.getBoundingClientRect(),\n parentNode.getBoundingClientRect()\n )\n )\n }\n\n return () => {\n Nodes.delete(node)\n LayoutHandlers.delete(node)\n NodeRectCache.delete(node)\n LastChangeTime.delete(node)\n IntersectionState.delete(node)\n\n // Remove from intersection observer\n if (globalIntersectionObserver) {\n globalIntersectionObserver.unobserve(node)\n }\n }\n }, [ref, !!onLayout])\n}\n\nfunction ensureWebElement<X>(x: X): HTMLElement | undefined {\n if (typeof HTMLElement === 'undefined') {\n return undefined\n }\n return x instanceof HTMLElement ? x : undefined\n}\n\nexport const getBoundingClientRectAsync = (\n node: HTMLElement | null\n): Promise<DOMRectReadOnly | false> => {\n return new Promise<DOMRectReadOnly | false>((res) => {\n if (!node || node.nodeType !== 1) return res(false)\n\n const io = new IntersectionObserver(\n (entries) => {\n io.disconnect()\n return res(entries[0].boundingClientRect)\n },\n {\n threshold: 0,\n }\n )\n io.observe(node)\n })\n}\n\nexport const measureNode = async (\n node: HTMLElement,\n relativeTo?: HTMLElement | null\n): Promise<null | LayoutValue> => {\n const relativeNode = relativeTo || node?.parentElement\n if (relativeNode instanceof HTMLElement) {\n const [nodeDim, relativeNodeDim] = await Promise.all([\n getBoundingClientRectAsync(node),\n getBoundingClientRectAsync(relativeNode),\n ])\n if (relativeNodeDim && nodeDim) {\n return getRelativeDimensions(nodeDim, relativeNodeDim)\n }\n }\n return null\n}\n\ntype MeasureInWindowCb = (x: number, y: number, width: number, height: number) => void\n\ntype MeasureCb = (\n x: number,\n y: number,\n width: number,\n height: number,\n pageX: number,\n pageY: number\n) => void\n\nexport const measure = async (\n node: HTMLElement,\n callback: MeasureCb\n): Promise<LayoutValue | null> => {\n const out = await measureNode(\n node,\n node.parentNode instanceof HTMLElement ? node.parentNode : null\n )\n if (out) {\n callback?.(out.x, out.y, out.width, out.height, out.pageX, out.pageY)\n }\n return out\n}\n\nexport function createMeasure(\n node: HTMLElement\n): (callback: MeasureCb) => Promise<LayoutValue | null> {\n return (callback) => measure(node, callback)\n}\n\ntype WindowLayout = { pageX: number; pageY: number; width: number; height: number }\n\nexport const measureInWindow = async (\n node: HTMLElement,\n callback: MeasureInWindowCb\n): Promise<WindowLayout | null> => {\n const out = await measureNode(node, null)\n if (out) {\n callback?.(out.pageX, out.pageY, out.width, out.height)\n }\n return out\n}\n\nexport const createMeasureInWindow = (\n node: HTMLElement\n): ((callback: MeasureInWindowCb) => Promise<WindowLayout | null>) => {\n return (callback) => measureInWindow(node, callback)\n}\n\nexport const measureLayout = async (\n node: HTMLElement,\n relativeNode: HTMLElement,\n callback: MeasureCb\n): Promise<LayoutValue | null> => {\n const out = await measureNode(node, relativeNode)\n if (out) {\n callback?.(out.x, out.y, out.width, out.height, out.pageX, out.pageY)\n }\n return out\n}\n\nexport function createMeasureLayout(\n node: HTMLElement\n): (relativeTo: HTMLElement, callback: MeasureCb) => Promise<LayoutValue | null> {\n return (relativeTo, callback) => measureLayout(node, relativeTo, callback)\n}\n"
|
|
28
|
+
"import { isClient, useIsomorphicLayoutEffect } from '@tamagui/constants'\nimport { isEqualShallow } from '@tamagui/is-equal-shallow'\nimport { createContext, useContext, useId, type ReactNode, type RefObject } from 'react'\n\nconst LayoutHandlers = new WeakMap<HTMLElement, Function>()\nconst LayoutDisableKey = new WeakMap<HTMLElement, string>()\nconst Nodes = new Set<HTMLElement>()\nconst IntersectionState = new WeakMap<HTMLElement, boolean>()\n\n// separating to avoid all re-rendering\nconst DisableLayoutContextValues: Record<string, boolean> = {}\nconst DisableLayoutContextKey = createContext<string>('')\n\nconst ENABLE = isClient && typeof IntersectionObserver !== 'undefined'\n\n// internal testing - advanced helper to turn off layout measurement for extra performance\n// TODO document!\n// TODO could add frame skip control here\nexport const LayoutMeasurementController = ({\n disable,\n children,\n}: {\n disable: boolean\n children: ReactNode\n}): ReactNode => {\n const id = useId()\n\n useIsomorphicLayoutEffect(() => {\n DisableLayoutContextValues[id] = disable\n }, [disable, id])\n\n return (\n <DisableLayoutContextKey.Provider value={id}>\n {children}\n </DisableLayoutContextKey.Provider>\n )\n}\n\n// Single persistent IntersectionObserver for all nodes\nlet globalIntersectionObserver: IntersectionObserver | null = null\n\ntype TamaguiComponentStatePartial = {\n host?: any\n}\n\ntype LayoutMeasurementStrategy = 'off' | 'sync' | 'async'\n\nlet strategy: LayoutMeasurementStrategy = 'async'\n\nexport function setOnLayoutStrategy(state: LayoutMeasurementStrategy): void {\n strategy = state\n}\n\nexport type LayoutValue = {\n x: number\n y: number\n width: number\n height: number\n pageX: number\n pageY: number\n}\n\nexport type LayoutEvent = {\n nativeEvent: {\n layout: LayoutValue\n target: any\n }\n timeStamp: number\n}\n\nconst NodeRectCache = new WeakMap<HTMLElement, DOMRect>()\nconst LastChangeTime = new WeakMap<HTMLElement, number>()\n\n// prevent thrashing during first hydration (somewhat, streaming gets trickier)\nlet avoidUpdates = true\nconst queuedUpdates = new Map<HTMLElement, Function>()\n\nexport function enable(): void {\n if (avoidUpdates) {\n avoidUpdates = false\n if (queuedUpdates) {\n queuedUpdates.forEach((cb) => cb())\n queuedUpdates.clear()\n }\n }\n}\n\nfunction startGlobalObservers() {\n if (!ENABLE || globalIntersectionObserver) return\n\n globalIntersectionObserver = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n const node = entry.target as HTMLElement\n if (IntersectionState.get(node) !== entry.isIntersecting) {\n IntersectionState.set(node, entry.isIntersecting)\n }\n })\n },\n {\n threshold: 0,\n }\n )\n}\n\nif (ENABLE) {\n const BoundingRects = new WeakMap<any, DOMRectReadOnly | undefined>()\n\n async function updateLayoutIfChanged(node: HTMLElement) {\n const onLayout = LayoutHandlers.get(node)\n if (typeof onLayout !== 'function') return\n\n const parentNode = node.parentElement\n if (!parentNode) return\n\n let nodeRect: DOMRectReadOnly\n let parentRect: DOMRectReadOnly\n\n if (strategy === 'async') {\n const [nr, pr] = await Promise.all([\n BoundingRects.get(node),\n BoundingRects.get(parentNode),\n ])\n\n if (!nr || !pr) {\n return\n }\n\n nodeRect = nr\n parentRect = pr\n } else {\n nodeRect = node.getBoundingClientRect()\n parentRect = parentNode.getBoundingClientRect()\n }\n\n if (!nodeRect || !parentRect) {\n return\n }\n\n const cachedRect = NodeRectCache.get(node)\n const cachedParentRect = NodeRectCache.get(parentNode)\n\n if (\n !cachedRect ||\n !cachedParentRect ||\n // has changed one rect\n // @ts-expect-error DOMRectReadOnly can go into object\n !isEqualShallow(cachedRect, nodeRect) ||\n // @ts-expect-error DOMRectReadOnly can go into object\n !isEqualShallow(cachedParentRect, parentRect)\n ) {\n NodeRectCache.set(node, nodeRect)\n NodeRectCache.set(parentNode, parentRect)\n\n const event = getElementLayoutEvent(nodeRect, parentRect)\n\n if (avoidUpdates) {\n queuedUpdates.set(node, () => onLayout(event))\n } else {\n onLayout(event)\n }\n }\n }\n\n // note that getBoundingClientRect() does not thrash layout if its after an animation frame\n // ok new note: *if* it needed recalc then yea, but browsers often skip that, so it does\n // which is why we use async strategy in general\n\n const userSkipVal = process.env.TAMAGUI_LAYOUT_FRAME_SKIP\n const RUN_EVERY_X_FRAMES = userSkipVal ? +userSkipVal : 14\n\n async function layoutOnAnimationFrame() {\n if (strategy !== 'off') {\n const visibleNodes: HTMLElement[] = []\n\n // do a 1 rather than N IntersectionObservers for performance\n const didRun = await new Promise<boolean>((res) => {\n const io = new IntersectionObserver(\n (entries) => {\n io.disconnect()\n for (const entry of entries) {\n BoundingRects.set(entry.target, entry.boundingClientRect)\n }\n res(true)\n },\n {\n threshold: 0,\n }\n )\n\n let didObserve = false\n\n for (const node of Nodes) {\n if (!(node.parentElement instanceof HTMLElement)) continue\n const disableKey = LayoutDisableKey.get(node)\n if (disableKey && DisableLayoutContextValues[disableKey] === true) continue\n if (IntersectionState.get(node) === false) continue\n didObserve = true\n io.observe(node)\n io.observe(node.parentElement)\n visibleNodes.push(node)\n }\n\n if (!didObserve) {\n res(false)\n }\n })\n\n if (didRun) {\n visibleNodes.forEach((node) => {\n updateLayoutIfChanged(node)\n })\n }\n }\n\n setTimeout(layoutOnAnimationFrame, 16.6667 * RUN_EVERY_X_FRAMES)\n }\n\n layoutOnAnimationFrame()\n}\n\nexport const getElementLayoutEvent = (\n nodeRect: DOMRectReadOnly,\n parentRect: DOMRectReadOnly\n): LayoutEvent => {\n return {\n nativeEvent: {\n layout: getRelativeDimensions(nodeRect, parentRect),\n target: nodeRect,\n },\n timeStamp: Date.now(),\n }\n}\n\nconst getRelativeDimensions = (a: DOMRectReadOnly, b: DOMRectReadOnly) => {\n const { height, left, top, width } = a\n const x = left - b.left\n const y = top - b.top\n return { x, y, width, height, pageX: a.left, pageY: a.top }\n}\n\nexport function useElementLayout(\n ref: RefObject<TamaguiComponentStatePartial>,\n onLayout?: ((e: LayoutEvent) => void) | null\n): void {\n const disableKey = useContext(DisableLayoutContextKey)\n\n // ensure always up to date so we can avoid re-running effect\n const node = ensureWebElement(ref.current?.host)\n if (node && onLayout) {\n LayoutHandlers.set(node, onLayout)\n LayoutDisableKey.set(node, disableKey)\n }\n\n useIsomorphicLayoutEffect(() => {\n if (!onLayout) return\n const node = ref.current?.host\n if (!node) return\n\n Nodes.add(node)\n\n // Add node to intersection observer\n startGlobalObservers()\n if (globalIntersectionObserver) {\n globalIntersectionObserver.observe(node)\n // Initialize as intersecting by default\n IntersectionState.set(node, true)\n }\n\n // always do one immediate sync layout event no matter the strategy for accuracy\n const parentNode = node.parentNode\n if (parentNode) {\n onLayout(\n getElementLayoutEvent(\n node.getBoundingClientRect(),\n parentNode.getBoundingClientRect()\n )\n )\n }\n\n return () => {\n Nodes.delete(node)\n LayoutHandlers.delete(node)\n NodeRectCache.delete(node)\n LastChangeTime.delete(node)\n IntersectionState.delete(node)\n\n // Remove from intersection observer\n if (globalIntersectionObserver) {\n globalIntersectionObserver.unobserve(node)\n }\n }\n }, [ref, !!onLayout])\n}\n\nfunction ensureWebElement<X>(x: X): HTMLElement | undefined {\n if (typeof HTMLElement === 'undefined') {\n return undefined\n }\n return x instanceof HTMLElement ? x : undefined\n}\n\nexport const getBoundingClientRectAsync = (\n node: HTMLElement | null\n): Promise<DOMRectReadOnly | false> => {\n return new Promise<DOMRectReadOnly | false>((res) => {\n if (!node || node.nodeType !== 1) return res(false)\n\n const io = new IntersectionObserver(\n (entries) => {\n io.disconnect()\n return res(entries[0].boundingClientRect)\n },\n {\n threshold: 0,\n }\n )\n io.observe(node)\n })\n}\n\nexport const measureNode = async (\n node: HTMLElement,\n relativeTo?: HTMLElement | null\n): Promise<null | LayoutValue> => {\n const relativeNode = relativeTo || node?.parentElement\n if (relativeNode instanceof HTMLElement) {\n const [nodeDim, relativeNodeDim] = await Promise.all([\n getBoundingClientRectAsync(node),\n getBoundingClientRectAsync(relativeNode),\n ])\n if (relativeNodeDim && nodeDim) {\n return getRelativeDimensions(nodeDim, relativeNodeDim)\n }\n }\n return null\n}\n\ntype MeasureInWindowCb = (x: number, y: number, width: number, height: number) => void\n\ntype MeasureCb = (\n x: number,\n y: number,\n width: number,\n height: number,\n pageX: number,\n pageY: number\n) => void\n\nexport const measure = async (\n node: HTMLElement,\n callback: MeasureCb\n): Promise<LayoutValue | null> => {\n const out = await measureNode(\n node,\n node.parentNode instanceof HTMLElement ? node.parentNode : null\n )\n if (out) {\n callback?.(out.x, out.y, out.width, out.height, out.pageX, out.pageY)\n }\n return out\n}\n\nexport function createMeasure(\n node: HTMLElement\n): (callback: MeasureCb) => Promise<LayoutValue | null> {\n return (callback) => measure(node, callback)\n}\n\ntype WindowLayout = { pageX: number; pageY: number; width: number; height: number }\n\nexport const measureInWindow = async (\n node: HTMLElement,\n callback: MeasureInWindowCb\n): Promise<WindowLayout | null> => {\n const out = await measureNode(node, null)\n if (out) {\n callback?.(out.pageX, out.pageY, out.width, out.height)\n }\n return out\n}\n\nexport const createMeasureInWindow = (\n node: HTMLElement\n): ((callback: MeasureInWindowCb) => Promise<WindowLayout | null>) => {\n return (callback) => measureInWindow(node, callback)\n}\n\nexport const measureLayout = async (\n node: HTMLElement,\n relativeNode: HTMLElement,\n callback: MeasureCb\n): Promise<LayoutValue | null> => {\n const out = await measureNode(node, relativeNode)\n if (out) {\n callback?.(out.x, out.y, out.width, out.height, out.pageX, out.pageY)\n }\n return out\n}\n\nexport function createMeasureLayout(\n node: HTMLElement\n): (relativeTo: HTMLElement, callback: MeasureCb) => Promise<LayoutValue | null> {\n return (relativeTo, callback) => measureLayout(node, relativeTo, callback)\n}\n"
|
|
29
29
|
],
|
|
30
30
|
"version": 3
|
|
31
31
|
}
|