@tamagui/use-element-layout 1.129.6 → 1.129.7

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.
@@ -1 +1 @@
1
- {"version":3,"names":["isClient","useIsomorphicLayoutEffect","isEqualShallow","LayoutHandlers","WeakMap","Nodes","Set","strategy","setOnLayoutStrategy","state","NodeRectCache","ParentRectCache","DebounceTimers","LastChangeTime","rAF","window","requestAnimationFrame","DEBOUNCE_DELAY","avoidUpdates","queuedUpdates","Map","enable","forEach","cb","clear","layoutOnAnimationFrame","now","Date","timeSinceLastFrame","lastFrameAt","expectedFrameTime","hasRecentSyncWork","numDroppedFramesUntilPause","updateLayoutIfChanged","layoutOnAnimationFrame2","node","nodeRect","getBoundingClientRect","parentNode","parentElement","parentRect","onLayout","get","cachedRect","cachedParentRect","set","event","getElementLayoutEvent","existingTimer","clearTimeout","timer","setTimeout","lastChange","timeSinceChange","event2","getElementLayoutEventAsync","delete","remainingDelay","newTimer","event3","event1","process","env","NODE_ENV","console","warn","target","res","measureLayout","x","y","width","height","left","top","nativeEvent","layout","timeStamp","Error","relativeTo","callback","relativeNode","HTMLElement","nodeDim","relativeNodeDim","getRelativeDimensions","measureLayoutAsync","Promise","all","a","b","useElementLayout","ref","_ref_current","ensureWebElement","current","host","_ref_current2","node2"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["isClient","useIsomorphicLayoutEffect","isEqualShallow","LayoutHandlers","WeakMap","Nodes","Set","strategy","setOnLayoutStrategy","state","NodeRectCache","ParentRectCache","LastChangeTime","rAF","window","requestAnimationFrame","avoidUpdates","queuedUpdates","Map","enable","forEach","cb","clear","layoutOnAnimationFrame","now","Date","timeSinceLastFrame","lastFrameAt","expectedFrameTime","hasRecentSyncWork","numDroppedFramesUntilPause","node","updateLayoutIfChanged","layoutOnAnimationFrame2","frameId","parentNode","parentElement","nodeRect","parentRect","nr","pr","Promise","all","getBoundingClientRectAsync","getBoundingClientRect","onLayout","get","cachedRect","cachedParentRect","set","event","getElementLayoutEvent","event1","process","env","NODE_ENV","console","warn","nativeEvent","layout","getRelativeDimensions","target","timeStamp","measureLayout","relativeTo","callback","relativeNode","HTMLElement","nodeDim","relativeNodeDim","x","y","width","height","left","top","getElementLayoutEventAsync","measureLayoutAsync","Error","a","b","useElementLayout","ref","_ref_current","ensureWebElement","current","host","_ref_current2","node2","add","delete","res","nodeType","io","IntersectionObserver","entries"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tamagui/use-element-layout",
3
- "version": "1.129.6",
3
+ "version": "1.129.7",
4
4
  "types": "./types/index.d.ts",
5
5
  "main": "dist/cjs",
6
6
  "module": "dist/esm",
@@ -31,11 +31,11 @@
31
31
  }
32
32
  },
33
33
  "dependencies": {
34
- "@tamagui/constants": "1.129.6",
35
- "@tamagui/is-equal-shallow": "1.129.6"
34
+ "@tamagui/constants": "1.129.7",
35
+ "@tamagui/is-equal-shallow": "1.129.7"
36
36
  },
37
37
  "devDependencies": {
38
- "@tamagui/build": "1.129.6",
38
+ "@tamagui/build": "1.129.7",
39
39
  "react": "*"
40
40
  },
41
41
  "publishConfig": {
package/src/index.ts CHANGED
@@ -40,7 +40,6 @@ const DebounceTimers = new WeakMap<HTMLElement, NodeJS.Timeout>()
40
40
  const LastChangeTime = new WeakMap<HTMLElement, number>()
41
41
 
42
42
  const rAF = typeof window !== 'undefined' ? window.requestAnimationFrame : undefined
43
- const DEBOUNCE_DELAY = 32 // 32ms debounce (2 frames at 60fps)
44
43
 
45
44
  // prevent thrashing during first hydration (somewhat, streaming gets trickier)
46
45
  let avoidUpdates = true
@@ -62,10 +61,33 @@ if (isClient) {
62
61
  let lastFrameAt = Date.now()
63
62
  const numDroppedFramesUntilPause = 2 // adjust sensitivity
64
63
 
65
- async function updateLayoutIfChanged(node: HTMLElement) {
66
- const nodeRect = node.getBoundingClientRect()
64
+ async function updateLayoutIfChanged(node: HTMLElement, frameId: number) {
67
65
  const parentNode = node.parentElement
68
- const parentRect = parentNode?.getBoundingClientRect()
66
+
67
+ let nodeRect: DOMRectReadOnly
68
+ let parentRect: DOMRectReadOnly | undefined
69
+
70
+ if (strategy === 'async') {
71
+ const [nr, pr] = await Promise.all([
72
+ getBoundingClientRectAsync(node),
73
+ getBoundingClientRectAsync(parentNode),
74
+ ])
75
+
76
+ // cancel if we skipped a frame
77
+ if (frameId !== lastFrameAt) {
78
+ return
79
+ }
80
+
81
+ nodeRect = nr
82
+ parentRect = pr
83
+ } else {
84
+ nodeRect = node.getBoundingClientRect()
85
+ parentRect = parentNode?.getBoundingClientRect()
86
+ }
87
+
88
+ if (!parentRect) {
89
+ return
90
+ }
69
91
 
70
92
  const onLayout = LayoutHandlers.get(node)
71
93
  if (typeof onLayout !== 'function') return
@@ -86,45 +108,12 @@ if (isClient) {
86
108
 
87
109
  if (avoidUpdates) {
88
110
  // Use sync version for queued updates to avoid promise complications
89
- const event = getElementLayoutEvent(node)
111
+ const event = getElementLayoutEvent(nodeRect, parentRect)
90
112
  queuedUpdates.set(node, () => onLayout(event))
91
113
  } else if (strategy === 'async') {
92
- // For async strategy, debounce the layout update
93
- const now = Date.now()
94
- LastChangeTime.set(node, now)
95
-
96
- // Clear existing debounce timer
97
- const existingTimer = DebounceTimers.get(node)
98
- if (existingTimer) {
99
- clearTimeout(existingTimer)
100
- }
101
-
102
- // Set new debounce timer
103
- const timer = setTimeout(async () => {
104
- const lastChange = LastChangeTime.get(node) || 0
105
- const timeSinceChange = Date.now() - lastChange
106
-
107
- // Only fire if at least DEBOUNCE_DELAY has passed since last change
108
- if (timeSinceChange >= DEBOUNCE_DELAY) {
109
- const event = await getElementLayoutEventAsync(node)
110
- onLayout(event)
111
- DebounceTimers.delete(node)
112
- } else {
113
- // Reschedule if not enough time has passed
114
- const remainingDelay = DEBOUNCE_DELAY - timeSinceChange
115
- const newTimer = setTimeout(async () => {
116
- const event = await getElementLayoutEventAsync(node)
117
- onLayout(event)
118
- DebounceTimers.delete(node)
119
- }, remainingDelay)
120
- DebounceTimers.set(node, newTimer)
121
- }
122
- }, DEBOUNCE_DELAY)
123
-
124
- DebounceTimers.set(node, timer)
125
114
  } else {
126
115
  // Sync strategy - use sync version
127
- const event = getElementLayoutEvent(node)
116
+ const event = getElementLayoutEvent(nodeRect, parentRect)
128
117
  onLayout(event)
129
118
  }
130
119
  }
@@ -139,15 +128,19 @@ if (isClient) {
139
128
  lastFrameAt = now
140
129
 
141
130
  if (strategy !== 'off') {
131
+ // for both strategies:
142
132
  // avoid updates if we've been dropping frames (indicates sync work happening)
143
133
  const expectedFrameTime = 16.67 // ~60fps
144
134
  const hasRecentSyncWork =
145
135
  timeSinceLastFrame > expectedFrameTime * numDroppedFramesUntilPause
146
136
 
147
137
  if (!hasRecentSyncWork) {
148
- Nodes.forEach(updateLayoutIfChanged)
138
+ Nodes.forEach((node) => {
139
+ updateLayoutIfChanged(node, lastFrameAt)
140
+ })
149
141
  }
150
142
  }
143
+
151
144
  rAF!(layoutOnAnimationFrame)
152
145
  }
153
146
  } else {
@@ -159,22 +152,17 @@ if (isClient) {
159
152
  }
160
153
  }
161
154
 
162
- // Sync versions
163
- export const getElementLayoutEvent = (target: HTMLElement): LayoutEvent => {
164
- let res: LayoutEvent | null = null
165
- measureLayout(target, null, (x, y, width, height, left, top) => {
166
- res = {
167
- nativeEvent: {
168
- layout: { x, y, width, height, left, top },
169
- target,
170
- },
171
- timeStamp: Date.now(),
172
- }
173
- })
174
- if (!res) {
175
- throw new Error(`‼️`) // impossible
155
+ export const getElementLayoutEvent = (
156
+ nodeRect: DOMRectReadOnly,
157
+ parentRect: DOMRectReadOnly
158
+ ): LayoutEvent => {
159
+ return {
160
+ nativeEvent: {
161
+ layout: getRelativeDimensions(nodeRect, parentRect),
162
+ target: nodeRect,
163
+ },
164
+ timeStamp: Date.now(),
176
165
  }
177
- return res
178
166
  }
179
167
 
180
168
  export const measureLayout = (
@@ -227,8 +215,8 @@ export const measureLayoutAsync = async (
227
215
  const relativeNode = relativeTo || node?.parentElement
228
216
  if (relativeNode instanceof HTMLElement) {
229
217
  const [nodeDim, relativeNodeDim] = await Promise.all([
230
- node.getBoundingClientRect(),
231
- relativeNode.getBoundingClientRect(),
218
+ getBoundingClientRectAsync(node),
219
+ getBoundingClientRectAsync(relativeNode),
232
220
  ])
233
221
 
234
222
  if (relativeNodeDim && nodeDim) {
@@ -266,19 +254,22 @@ export function useElementLayout(
266
254
 
267
255
  LayoutHandlers.set(node, onLayout)
268
256
  Nodes.add(node)
269
- onLayout(getElementLayoutEvent(node))
257
+
258
+ // always do one immediate sync layout event no matter the strategy for accuracy
259
+ const parentNode = node.parentNode
260
+ if (parentNode) {
261
+ onLayout(
262
+ getElementLayoutEvent(
263
+ node.getBoundingClientRect(),
264
+ parentNode.getBoundingClientRect()
265
+ )
266
+ )
267
+ }
270
268
 
271
269
  return () => {
272
270
  Nodes.delete(node)
273
271
  LayoutHandlers.delete(node)
274
272
  NodeRectCache.delete(node)
275
-
276
- // Clean up debounce timer and tracking
277
- const timer = DebounceTimers.get(node)
278
- if (timer) {
279
- clearTimeout(timer)
280
- DebounceTimers.delete(node)
281
- }
282
273
  LastChangeTime.delete(node)
283
274
  }
284
275
  }, [ref, !!onLayout])
@@ -291,6 +282,24 @@ function ensureWebElement<X>(x: X): HTMLElement | undefined {
291
282
  return x instanceof HTMLElement ? x : undefined
292
283
  }
293
284
 
285
+ const getBoundingClientRectAsync = (
286
+ node: HTMLElement | null
287
+ ): Promise<DOMRectReadOnly> => {
288
+ return new Promise<DOMRectReadOnly>((res) => {
289
+ if (!node || node.nodeType !== 1) return
290
+ const io = new IntersectionObserver(
291
+ (entries) => {
292
+ io.disconnect()
293
+ return res(entries[0].boundingClientRect)
294
+ },
295
+ {
296
+ threshold: 0,
297
+ }
298
+ )
299
+ io.observe(node)
300
+ })
301
+ }
302
+
294
303
  const getBoundingClientRect = (node: HTMLElement | null): undefined | DOMRect => {
295
304
  if (!node || node.nodeType !== 1) return
296
305
  return node.getBoundingClientRect?.()
package/types/index.d.ts CHANGED
@@ -20,8 +20,7 @@ export type LayoutEvent = {
20
20
  timeStamp: number;
21
21
  };
22
22
  export declare function enable(): void;
23
- // Sync versions
24
- export declare const getElementLayoutEvent: (target: HTMLElement) => LayoutEvent;
23
+ export declare const getElementLayoutEvent: (nodeRect: DOMRectReadOnly, parentRect: DOMRectReadOnly) => LayoutEvent;
25
24
  export declare const measureLayout: (node: HTMLElement, relativeTo: HTMLElement | null, callback: (x: number, y: number, width: number, height: number, left: number, top: number) => void) => void;
26
25
  export declare const getElementLayoutEventAsync: (target: HTMLElement) => Promise<LayoutEvent>;
27
26
  export declare const measureLayoutAsync: (node: HTMLElement, relativeTo?: HTMLElement | null) => Promise<null | LayoutValue>;
@@ -1,8 +1,9 @@
1
1
  {
2
- "mappings": "AAEA,cAAc,iBAAiB,OAAO;KAKjC,+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;AAcD,OAAO,iBAAS;;AAkHhB,OAAO,cAAM,wBAAyBC,QAAQ,gBAAc;AAiB5D,OAAO,cAAM,gBACXC,MAAM,aACNC,YAAY,oBACZC,WACEC,WACAC,WACAC,eACAC,gBACAC,cACAC;AAkBJ,OAAO,cAAM,6BACXT,QAAQ,gBACP,QAAQ;AAcX,OAAO,cAAM,qBACXC,MAAM,aACNS,aAAa,uBACZ,eAAe;AA0BlB,OAAO,iBAAS,iBACdC,KAAK,UAAU,+BACfC,aAAaC,GAAG;AA6ClB,OAAO,cAAM,UAAWZ,MAAM,gBAAc",
2
+ "mappings": "AAEA,cAAc,iBAAiB,OAAO;KAKjC,+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;AAaD,OAAO,iBAAS;AA2GhB,OAAO,cAAM,wBACXC,UAAU,iBACVC,YAAY,oBACX;AAUH,OAAO,cAAM,gBACXC,MAAM,aACNC,YAAY,oBACZC,WACEC,WACAC,WACAC,eACAC,gBACAC,cACAC;AAkBJ,OAAO,cAAM,6BACXC,QAAQ,gBACP,QAAQ;AAcX,OAAO,cAAM,qBACXT,MAAM,aACNU,aAAa,uBACZ,eAAe;AA0BlB,OAAO,iBAAS,iBACdC,KAAK,UAAU,+BACfC,aAAaC,GAAG;AAkElB,OAAO,cAAM,UAAWb,MAAM,gBAAc",
3
3
  "names": [
4
4
  "state: LayoutMeasurementStrategy",
5
- "target: HTMLElement",
5
+ "nodeRect: DOMRectReadOnly",
6
+ "parentRect: DOMRectReadOnly",
6
7
  "node: HTMLElement",
7
8
  "relativeTo: HTMLElement | null",
8
9
  "callback: (\n x: number,\n y: number,\n width: number,\n height: number,\n left: number,\n top: number\n ) => void",
@@ -12,6 +13,7 @@
12
13
  "height: number",
13
14
  "left: number",
14
15
  "top: number",
16
+ "target: HTMLElement",
15
17
  "relativeTo?: HTMLElement | null",
16
18
  "ref: RefObject<TamaguiComponentStatePartial>",
17
19
  "onLayout?: ((e: LayoutEvent) => void) | null",
@@ -21,7 +23,7 @@
21
23
  "src/index.ts"
22
24
  ],
23
25
  "sourcesContent": [
24
- "import { isClient, useIsomorphicLayoutEffect } from '@tamagui/constants'\nimport { isEqualShallow } from '@tamagui/is-equal-shallow'\nimport type { RefObject } from 'react'\n\nconst LayoutHandlers = new WeakMap<HTMLElement, Function>()\nconst Nodes = new Set<HTMLElement>()\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 left: number\n top: 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 DebounceTimers = new WeakMap<HTMLElement, NodeJS.Timeout>()\nconst LastChangeTime = new WeakMap<HTMLElement, number>()\n\nconst rAF = typeof window !== 'undefined' ? window.requestAnimationFrame : undefined\nconst DEBOUNCE_DELAY = 32 // 32ms debounce (2 frames at 60fps)\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\nif (isClient) {\n if (rAF) {\n // track frame timing to detect sync work and avoid updates during heavy periods\n let lastFrameAt = Date.now()\n const numDroppedFramesUntilPause = 2 // adjust sensitivity\n\n async function updateLayoutIfChanged(node: HTMLElement) {\n const nodeRect = node.getBoundingClientRect()\n const parentNode = node.parentElement\n const parentRect = parentNode?.getBoundingClientRect()\n\n const onLayout = LayoutHandlers.get(node)\n if (typeof onLayout !== 'function') return\n\n const cachedRect = NodeRectCache.get(node)\n const cachedParentRect = parentNode ? NodeRectCache.get(parentNode) : null\n\n if (\n !cachedRect ||\n // has changed one rect\n (!isEqualShallow(cachedRect, nodeRect) &&\n (!cachedParentRect || !isEqualShallow(cachedParentRect, parentRect)))\n ) {\n NodeRectCache.set(node, nodeRect)\n if (parentRect && parentNode) {\n ParentRectCache.set(parentNode, parentRect)\n }\n\n if (avoidUpdates) {\n // Use sync version for queued updates to avoid promise complications\n const event = getElementLayoutEvent(node)\n queuedUpdates.set(node, () => onLayout(event))\n } else if (strategy === 'async') {\n // For async strategy, debounce the layout update\n const now = Date.now()\n LastChangeTime.set(node, now)\n\n // Clear existing debounce timer\n const existingTimer = DebounceTimers.get(node)\n if (existingTimer) {\n clearTimeout(existingTimer)\n }\n\n // Set new debounce timer\n const timer = setTimeout(async () => {\n const lastChange = LastChangeTime.get(node) || 0\n const timeSinceChange = Date.now() - lastChange\n\n // Only fire if at least DEBOUNCE_DELAY has passed since last change\n if (timeSinceChange >= DEBOUNCE_DELAY) {\n const event = await getElementLayoutEventAsync(node)\n onLayout(event)\n DebounceTimers.delete(node)\n } else {\n // Reschedule if not enough time has passed\n const remainingDelay = DEBOUNCE_DELAY - timeSinceChange\n const newTimer = setTimeout(async () => {\n const event = await getElementLayoutEventAsync(node)\n onLayout(event)\n DebounceTimers.delete(node)\n }, remainingDelay)\n DebounceTimers.set(node, newTimer)\n }\n }, DEBOUNCE_DELAY)\n\n DebounceTimers.set(node, timer)\n } else {\n // Sync strategy - use sync version\n const event = getElementLayoutEvent(node)\n onLayout(event)\n }\n }\n }\n\n // note that getBoundingClientRect() does not thrash layout if its after an animation frame\n rAF!(layoutOnAnimationFrame)\n\n function layoutOnAnimationFrame() {\n const now = Date.now()\n const timeSinceLastFrame = now - lastFrameAt\n lastFrameAt = now\n\n if (strategy !== 'off') {\n // avoid updates if we've been dropping frames (indicates sync work happening)\n const expectedFrameTime = 16.67 // ~60fps\n const hasRecentSyncWork =\n timeSinceLastFrame > expectedFrameTime * numDroppedFramesUntilPause\n\n if (!hasRecentSyncWork) {\n Nodes.forEach(updateLayoutIfChanged)\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\n// Sync versions\nexport const getElementLayoutEvent = (target: HTMLElement): LayoutEvent => {\n let res: LayoutEvent | null = null\n measureLayout(target, null, (x, y, width, height, left, top) => {\n res = {\n nativeEvent: {\n layout: { x, y, width, height, left, top },\n target,\n },\n timeStamp: Date.now(),\n }\n })\n if (!res) {\n throw new Error(`‼️`) // impossible\n }\n return res\n}\n\nexport const measureLayout = (\n node: HTMLElement,\n relativeTo: HTMLElement | null,\n callback: (\n x: number,\n y: number,\n width: number,\n height: number,\n left: number,\n top: number\n ) => void\n): void => {\n const relativeNode = relativeTo || node?.parentElement\n if (relativeNode instanceof HTMLElement) {\n const nodeDim = node.getBoundingClientRect()\n const relativeNodeDim = relativeNode.getBoundingClientRect()\n\n if (relativeNodeDim && nodeDim) {\n const { x, y, width, height, left, top } = getRelativeDimensions(\n nodeDim,\n relativeNodeDim\n )\n callback(x, y, width, height, left, top)\n }\n }\n}\n\nexport const getElementLayoutEventAsync = async (\n target: HTMLElement\n): Promise<LayoutEvent> => {\n const layout = await measureLayoutAsync(target)\n if (!layout) {\n throw new Error(`‼️`) // impossible\n }\n return {\n nativeEvent: {\n layout,\n target,\n },\n timeStamp: Date.now(),\n }\n}\n\nexport const measureLayoutAsync = 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 node.getBoundingClientRect(),\n relativeNode.getBoundingClientRect(),\n ])\n\n if (relativeNodeDim && nodeDim) {\n const { x, y, width, height, left, top } = getRelativeDimensions(\n nodeDim,\n relativeNodeDim\n )\n return { x, y, width, height, left, top }\n }\n }\n return null\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, left, 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 LayoutHandlers.set(node, onLayout)\n Nodes.add(node)\n onLayout(getElementLayoutEvent(node))\n\n return () => {\n Nodes.delete(node)\n LayoutHandlers.delete(node)\n NodeRectCache.delete(node)\n\n // Clean up debounce timer and tracking\n const timer = DebounceTimers.get(node)\n if (timer) {\n clearTimeout(timer)\n DebounceTimers.delete(node)\n }\n LastChangeTime.delete(node)\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\nconst getBoundingClientRect = (node: HTMLElement | null): undefined | DOMRect => {\n if (!node || node.nodeType !== 1) return\n return node.getBoundingClientRect?.()\n}\n\nexport const getRect = (node: HTMLElement): LayoutValue | undefined => {\n const rect = getBoundingClientRect(node)\n if (!rect) return\n const { x, y, top, left } = rect\n return { x, y, width: node.offsetWidth, height: node.offsetHeight, top, left }\n}\n"
26
+ "import { isClient, useIsomorphicLayoutEffect } from '@tamagui/constants'\nimport { isEqualShallow } from '@tamagui/is-equal-shallow'\nimport type { RefObject } from 'react'\n\nconst LayoutHandlers = new WeakMap<HTMLElement, Function>()\nconst Nodes = new Set<HTMLElement>()\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 left: number\n top: 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 DebounceTimers = new WeakMap<HTMLElement, NodeJS.Timeout>()\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\nif (isClient) {\n if (rAF) {\n // track frame timing to detect sync work and avoid updates during heavy periods\n let lastFrameAt = Date.now()\n const numDroppedFramesUntilPause = 2 // adjust sensitivity\n\n async function updateLayoutIfChanged(node: HTMLElement, frameId: number) {\n const parentNode = node.parentElement\n\n let nodeRect: DOMRectReadOnly\n let parentRect: DOMRectReadOnly | undefined\n\n if (strategy === 'async') {\n const [nr, pr] = await Promise.all([\n getBoundingClientRectAsync(node),\n getBoundingClientRectAsync(parentNode),\n ])\n\n // cancel if we skipped a frame\n if (frameId !== lastFrameAt) {\n return\n }\n\n nodeRect = nr\n parentRect = pr\n } else {\n nodeRect = node.getBoundingClientRect()\n parentRect = parentNode?.getBoundingClientRect()\n }\n\n if (!parentRect) {\n return\n }\n\n const onLayout = LayoutHandlers.get(node)\n if (typeof onLayout !== 'function') return\n\n const cachedRect = NodeRectCache.get(node)\n const cachedParentRect = parentNode ? NodeRectCache.get(parentNode) : null\n\n if (\n !cachedRect ||\n // has changed one rect\n (!isEqualShallow(cachedRect, nodeRect) &&\n (!cachedParentRect || !isEqualShallow(cachedParentRect, parentRect)))\n ) {\n NodeRectCache.set(node, nodeRect)\n if (parentRect && parentNode) {\n ParentRectCache.set(parentNode, parentRect)\n }\n\n if (avoidUpdates) {\n // Use sync version for queued updates to avoid promise complications\n const event = getElementLayoutEvent(nodeRect, parentRect)\n queuedUpdates.set(node, () => onLayout(event))\n } else if (strategy === 'async') {\n } else {\n // Sync strategy - use sync version\n const event = getElementLayoutEvent(nodeRect, parentRect)\n onLayout(event)\n }\n }\n }\n\n // note that getBoundingClientRect() does not thrash layout if its after an animation frame\n rAF!(layoutOnAnimationFrame)\n\n function layoutOnAnimationFrame() {\n const now = Date.now()\n const timeSinceLastFrame = now - lastFrameAt\n lastFrameAt = now\n\n if (strategy !== 'off') {\n // for both strategies:\n // avoid updates if we've been dropping frames (indicates sync work happening)\n const expectedFrameTime = 16.67 // ~60fps\n const hasRecentSyncWork =\n timeSinceLastFrame > expectedFrameTime * numDroppedFramesUntilPause\n\n if (!hasRecentSyncWork) {\n Nodes.forEach((node) => {\n updateLayoutIfChanged(node, lastFrameAt)\n })\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\nexport const measureLayout = (\n node: HTMLElement,\n relativeTo: HTMLElement | null,\n callback: (\n x: number,\n y: number,\n width: number,\n height: number,\n left: number,\n top: number\n ) => void\n): void => {\n const relativeNode = relativeTo || node?.parentElement\n if (relativeNode instanceof HTMLElement) {\n const nodeDim = node.getBoundingClientRect()\n const relativeNodeDim = relativeNode.getBoundingClientRect()\n\n if (relativeNodeDim && nodeDim) {\n const { x, y, width, height, left, top } = getRelativeDimensions(\n nodeDim,\n relativeNodeDim\n )\n callback(x, y, width, height, left, top)\n }\n }\n}\n\nexport const getElementLayoutEventAsync = async (\n target: HTMLElement\n): Promise<LayoutEvent> => {\n const layout = await measureLayoutAsync(target)\n if (!layout) {\n throw new Error(`‼️`) // impossible\n }\n return {\n nativeEvent: {\n layout,\n target,\n },\n timeStamp: Date.now(),\n }\n}\n\nexport const measureLayoutAsync = 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\n if (relativeNodeDim && nodeDim) {\n const { x, y, width, height, left, top } = getRelativeDimensions(\n nodeDim,\n relativeNodeDim\n )\n return { x, y, width, height, left, top }\n }\n }\n return null\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, left, 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 LayoutHandlers.set(node, onLayout)\n Nodes.add(node)\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 }\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\nconst getBoundingClientRectAsync = (\n node: HTMLElement | null\n): Promise<DOMRectReadOnly> => {\n return new Promise<DOMRectReadOnly>((res) => {\n if (!node || node.nodeType !== 1) return\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\nconst getBoundingClientRect = (node: HTMLElement | null): undefined | DOMRect => {\n if (!node || node.nodeType !== 1) return\n return node.getBoundingClientRect?.()\n}\n\nexport const getRect = (node: HTMLElement): LayoutValue | undefined => {\n const rect = getBoundingClientRect(node)\n if (!rect) return\n const { x, y, top, left } = rect\n return { x, y, width: node.offsetWidth, height: node.offsetHeight, top, left }\n}\n"
25
27
  ],
26
28
  "version": 3
27
29
  }