@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.
@@ -1,17 +1,34 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
1
2
  import { isClient, useIsomorphicLayoutEffect } from "@tamagui/constants";
2
3
  import { isEqualShallow } from "@tamagui/is-equal-shallow";
4
+ import { createContext, useContext, useId } from "react";
3
5
  var LayoutHandlers = /* @__PURE__ */new WeakMap(),
6
+ LayoutDisableKey = /* @__PURE__ */new WeakMap(),
4
7
  Nodes = /* @__PURE__ */new Set(),
5
8
  IntersectionState = /* @__PURE__ */new WeakMap(),
9
+ DisableLayoutContextValues = {},
10
+ DisableLayoutContextKey = /* @__PURE__ */createContext(""),
11
+ ENABLE = isClient && typeof IntersectionObserver < "u",
12
+ LayoutMeasurementController = function (param) {
13
+ var {
14
+ disable,
15
+ children
16
+ } = param,
17
+ id = useId();
18
+ return useIsomorphicLayoutEffect(function () {
19
+ DisableLayoutContextValues[id] = disable;
20
+ }, [disable, id]), /* @__PURE__ */_jsx(DisableLayoutContextKey.Provider, {
21
+ value: id,
22
+ children
23
+ });
24
+ },
6
25
  globalIntersectionObserver = null,
7
26
  strategy = "async";
8
27
  function setOnLayoutStrategy(state) {
9
28
  strategy = state;
10
29
  }
11
30
  var NodeRectCache = /* @__PURE__ */new WeakMap(),
12
- ParentRectCache = /* @__PURE__ */new WeakMap(),
13
31
  LastChangeTime = /* @__PURE__ */new WeakMap(),
14
- rAF = typeof window < "u" ? window.requestAnimationFrame : void 0,
15
32
  avoidUpdates = !0,
16
33
  queuedUpdates = /* @__PURE__ */new Map();
17
34
  function enable() {
@@ -20,7 +37,7 @@ function enable() {
20
37
  }), queuedUpdates.clear()));
21
38
  }
22
39
  function startGlobalObservers() {
23
- !isClient || globalIntersectionObserver || (globalIntersectionObserver = new IntersectionObserver(function (entries) {
40
+ !ENABLE || globalIntersectionObserver || (globalIntersectionObserver = new IntersectionObserver(function (entries) {
24
41
  entries.forEach(function (entry) {
25
42
  var node = entry.target;
26
43
  IntersectionState.get(node) !== entry.isIntersecting && IntersectionState.set(node, entry.isIntersecting);
@@ -29,30 +46,29 @@ function startGlobalObservers() {
29
46
  threshold: 0
30
47
  }));
31
48
  }
32
- if (isClient) if (rAF) {
33
- var supportsCheckVisibility = "checkVisibility" in document.body,
34
- BoundingRects = /* @__PURE__ */new WeakMap();
49
+ if (ENABLE) {
50
+ var BoundingRects = /* @__PURE__ */new WeakMap();
35
51
  async function updateLayoutIfChanged(node) {
36
- if (IntersectionState.get(node) !== !1 && !(process.env.TAMAGUI_ONLAYOUT_VISIBILITY_CHECK === "1" && supportsCheckVisibility && !node.checkVisibility())) {
37
- var onLayout = LayoutHandlers.get(node);
38
- if (typeof onLayout == "function") {
39
- var parentNode = node.parentElement;
40
- if (parentNode) {
41
- var nodeRect, parentRect;
42
- if (strategy === "async") {
43
- var [nr, pr] = await Promise.all([BoundingRects.get(node) || getBoundingClientRectAsync(node), BoundingRects.get(parentNode) || getBoundingClientRectAsync(parentNode)]);
44
- if (nr === !1 || pr === !1) return;
45
- nodeRect = nr, parentRect = pr;
46
- } else nodeRect = node.getBoundingClientRect(), parentRect = parentNode.getBoundingClientRect();
52
+ var onLayout = LayoutHandlers.get(node);
53
+ if (typeof onLayout == "function") {
54
+ var parentNode = node.parentElement;
55
+ if (parentNode) {
56
+ var nodeRect, parentRect;
57
+ if (strategy === "async") {
58
+ var [nr, pr] = await Promise.all([BoundingRects.get(node), BoundingRects.get(parentNode)]);
59
+ if (!nr || !pr) return;
60
+ nodeRect = nr, parentRect = pr;
61
+ } else nodeRect = node.getBoundingClientRect(), parentRect = parentNode.getBoundingClientRect();
62
+ if (!(!nodeRect || !parentRect)) {
47
63
  var cachedRect = NodeRectCache.get(node),
48
64
  cachedParentRect = NodeRectCache.get(parentNode);
49
- if (!cachedRect ||
65
+ if (!cachedRect || !cachedParentRect ||
50
66
  // has changed one rect
51
67
  // @ts-expect-error DOMRectReadOnly can go into object
52
- !isEqualShallow(cachedRect, nodeRect) && (
68
+ !isEqualShallow(cachedRect, nodeRect) ||
53
69
  // @ts-expect-error DOMRectReadOnly can go into object
54
- !cachedParentRect || !isEqualShallow(cachedParentRect, parentRect))) {
55
- NodeRectCache.set(node, nodeRect), ParentRectCache.set(parentNode, parentRect);
70
+ !isEqualShallow(cachedParentRect, parentRect)) {
71
+ NodeRectCache.set(node, nodeRect), NodeRectCache.set(parentNode, parentRect);
56
72
  var event = getElementLayoutEvent(nodeRect, parentRect);
57
73
  avoidUpdates ? queuedUpdates.set(node, function () {
58
74
  return onLayout(event);
@@ -62,64 +78,66 @@ if (isClient) if (rAF) {
62
78
  }
63
79
  }
64
80
  }
65
- rAF(layoutOnAnimationFrame);
66
- var frameCount = 0,
67
- userSkipVal = process.env.TAMAGUI_LAYOUT_FRAME_SKIP,
68
- RUN_EVERY_X_FRAMES = userSkipVal ? +userSkipVal : 10;
81
+ var userSkipVal = process.env.TAMAGUI_LAYOUT_FRAME_SKIP,
82
+ RUN_EVERY_X_FRAMES = userSkipVal ? +userSkipVal : 14;
69
83
  async function layoutOnAnimationFrame() {
70
84
  if (strategy !== "off") {
71
- if (!Nodes.size || frameCount++ % RUN_EVERY_X_FRAMES !== 0) {
72
- rAF(layoutOnAnimationFrame);
73
- return;
74
- }
75
- frameCount === Number.MAX_SAFE_INTEGER && (frameCount = 0), await new Promise(function (res) {
76
- var io = new IntersectionObserver(function (entries) {
77
- io.disconnect();
78
- var _iteratorNormalCompletion2 = !0,
79
- _didIteratorError2 = !1,
80
- _iteratorError2 = void 0;
81
- try {
82
- for (var _iterator2 = entries[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = !0) {
83
- var entry = _step2.value;
84
- BoundingRects.set(entry.target, entry.boundingClientRect);
85
- }
86
- } catch (err) {
87
- _didIteratorError2 = !0, _iteratorError2 = err;
88
- } finally {
85
+ var visibleNodes = [],
86
+ didRun = await new Promise(function (res) {
87
+ var io = new IntersectionObserver(function (entries) {
88
+ io.disconnect();
89
+ var _iteratorNormalCompletion2 = !0,
90
+ _didIteratorError2 = !1,
91
+ _iteratorError2 = void 0;
89
92
  try {
90
- !_iteratorNormalCompletion2 && _iterator2.return != null && _iterator2.return();
93
+ for (var _iterator2 = entries[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = !0) {
94
+ var entry = _step2.value;
95
+ BoundingRects.set(entry.target, entry.boundingClientRect);
96
+ }
97
+ } catch (err) {
98
+ _didIteratorError2 = !0, _iteratorError2 = err;
91
99
  } finally {
92
- if (_didIteratorError2) throw _iteratorError2;
100
+ try {
101
+ !_iteratorNormalCompletion2 && _iterator2.return != null && _iterator2.return();
102
+ } finally {
103
+ if (_didIteratorError2) throw _iteratorError2;
104
+ }
93
105
  }
94
- }
95
- res();
96
- }, {
97
- threshold: 0
98
- }),
99
- _iteratorNormalCompletion = !0,
100
- _didIteratorError = !1,
101
- _iteratorError = void 0;
102
- try {
103
- for (var _iterator = Nodes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = !0) {
104
- var node = _step.value;
105
- node.parentElement instanceof HTMLElement && (io.observe(node), io.observe(node.parentElement));
106
- }
107
- } catch (err) {
108
- _didIteratorError = !0, _iteratorError = err;
109
- } finally {
106
+ res(!0);
107
+ }, {
108
+ threshold: 0
109
+ }),
110
+ didObserve = !1,
111
+ _iteratorNormalCompletion = !0,
112
+ _didIteratorError = !1,
113
+ _iteratorError = void 0;
110
114
  try {
111
- !_iteratorNormalCompletion && _iterator.return != null && _iterator.return();
115
+ for (var _iterator = Nodes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = !0) {
116
+ var node = _step.value;
117
+ if (node.parentElement instanceof HTMLElement) {
118
+ var disableKey = LayoutDisableKey.get(node);
119
+ disableKey && DisableLayoutContextValues[disableKey] === !0 || IntersectionState.get(node) !== !1 && (didObserve = !0, io.observe(node), io.observe(node.parentElement), visibleNodes.push(node));
120
+ }
121
+ }
122
+ } catch (err) {
123
+ _didIteratorError = !0, _iteratorError = err;
112
124
  } finally {
113
- if (_didIteratorError) throw _iteratorError;
125
+ try {
126
+ !_iteratorNormalCompletion && _iterator.return != null && _iterator.return();
127
+ } finally {
128
+ if (_didIteratorError) throw _iteratorError;
129
+ }
114
130
  }
115
- }
116
- }), Nodes.forEach(function (node) {
131
+ didObserve || res(!1);
132
+ });
133
+ didRun && visibleNodes.forEach(function (node) {
117
134
  updateLayoutIfChanged(node);
118
135
  });
119
136
  }
120
- rAF(layoutOnAnimationFrame);
137
+ setTimeout(layoutOnAnimationFrame, 16.6667 * RUN_EVERY_X_FRAMES);
121
138
  }
122
- } else process.env.NODE_ENV === "development" && console.warn("No requestAnimationFrame - please polyfill for onLayout to work correctly");
139
+ layoutOnAnimationFrame();
140
+ }
123
141
  var getElementLayoutEvent = function (nodeRect, parentRect) {
124
142
  return {
125
143
  nativeEvent: {
@@ -149,8 +167,9 @@ var getElementLayoutEvent = function (nodeRect, parentRect) {
149
167
  };
150
168
  function useElementLayout(ref, onLayout) {
151
169
  var _ref_current,
170
+ disableKey = useContext(DisableLayoutContextKey),
152
171
  node = ensureWebElement((_ref_current = ref.current) === null || _ref_current === void 0 ? void 0 : _ref_current.host);
153
- node && onLayout && LayoutHandlers.set(node, onLayout), useIsomorphicLayoutEffect(function () {
172
+ node && onLayout && (LayoutHandlers.set(node, onLayout), LayoutDisableKey.set(node, disableKey)), useIsomorphicLayoutEffect(function () {
154
173
  var _ref_current2;
155
174
  if (onLayout) {
156
175
  var node2 = (_ref_current2 = ref.current) === null || _ref_current2 === void 0 ? void 0 : _ref_current2.host;
@@ -213,5 +232,5 @@ function createMeasureLayout(node) {
213
232
  return measureLayout(node, relativeTo, callback);
214
233
  };
215
234
  }
216
- export { createMeasure, createMeasureInWindow, createMeasureLayout, enable, getBoundingClientRectAsync, getElementLayoutEvent, measure, measureInWindow, measureLayout, measureNode, setOnLayoutStrategy, useElementLayout };
235
+ export { LayoutMeasurementController, createMeasure, createMeasureInWindow, createMeasureLayout, enable, getBoundingClientRectAsync, getElementLayoutEvent, measure, measureInWindow, measureLayout, measureNode, setOnLayoutStrategy, useElementLayout };
217
236
  //# sourceMappingURL=index.native.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["isClient","useIsomorphicLayoutEffect","isEqualShallow","LayoutHandlers","WeakMap","Nodes","Set","IntersectionState","globalIntersectionObserver","strategy","setOnLayoutStrategy","state","NodeRectCache","ParentRectCache","LastChangeTime","rAF","window","requestAnimationFrame","avoidUpdates","queuedUpdates","Map","enable","forEach","cb","clear","startGlobalObservers","IntersectionObserver","entries","entry","node","target","get","isIntersecting","set","threshold","supportsCheckVisibility","document","body","BoundingRects","updateLayoutIfChanged","process","env","TAMAGUI_ONLAYOUT_VISIBILITY_CHECK","checkVisibility","onLayout","parentNode","parentElement","nodeRect","parentRect","nr","pr","Promise","all","getBoundingClientRectAsync","getBoundingClientRect","cachedRect","cachedParentRect","event","getElementLayoutEvent","layoutOnAnimationFrame","frameCount","userSkipVal","TAMAGUI_LAYOUT_FRAME_SKIP","RUN_EVERY_X_FRAMES","size","Number","MAX_SAFE_INTEGER","res","io","disconnect","_iteratorNormalCompletion2","_didIteratorError2","_iteratorError2","_iterator2","Symbol","iterator","_step2","next","done","value","boundingClientRect","err","return","_iteratorNormalCompletion","_didIteratorError","_iteratorError","_iterator","_step","HTMLElement","observe","NODE_ENV","console","warn","nativeEvent","layout","getRelativeDimensions","timeStamp","Date","now","a","b","height","left","top","width","x","y","pageX","pageY","useElementLayout","ref","_ref_current","ensureWebElement","current","host","_ref_current2","node2","add","delete","unobserve","nodeType"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["jsx","_jsx","isClient","useIsomorphicLayoutEffect","isEqualShallow","createContext","useContext","useId","LayoutHandlers","WeakMap","LayoutDisableKey","Nodes","Set","IntersectionState","DisableLayoutContextValues","DisableLayoutContextKey","ENABLE","IntersectionObserver","LayoutMeasurementController","param","disable","children","id","Provider","value","globalIntersectionObserver","strategy","setOnLayoutStrategy","state","NodeRectCache","LastChangeTime","avoidUpdates","queuedUpdates","Map","enable","forEach","cb","clear","startGlobalObservers","entries","entry","node","target","get","isIntersecting","set","threshold","BoundingRects","updateLayoutIfChanged","onLayout","parentNode","parentElement","nodeRect","parentRect","nr","pr","Promise","all","getBoundingClientRect","cachedRect","cachedParentRect","event","getElementLayoutEvent","userSkipVal","process","env","TAMAGUI_LAYOUT_FRAME_SKIP","RUN_EVERY_X_FRAMES","layoutOnAnimationFrame","visibleNodes","didRun","res","io","disconnect","_iteratorNormalCompletion2","_didIteratorError2","_iteratorError2","_iterator2","Symbol","iterator","_step2","next","done","boundingClientRect","err","return","didObserve","_iteratorNormalCompletion","_didIteratorError","_iteratorError","_iterator","_step","HTMLElement","disableKey","observe","push","setTimeout","nativeEvent","layout","getRelativeDimensions","timeStamp","Date","now","a","b","height","left","top","width","x","y","pageX","pageY","useElementLayout","ref","_ref_current","ensureWebElement","current","host","_ref_current2","node2","add","delete","unobserve","getBoundingClientRectAsync","nodeType"],"sources":["../../src/index.tsx"],"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.134.5",
3
+ "version": "1.135.1",
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.134.5",
35
- "@tamagui/is-equal-shallow": "1.134.5"
34
+ "@tamagui/constants": "1.135.1",
35
+ "@tamagui/is-equal-shallow": "1.135.1"
36
36
  },
37
37
  "devDependencies": {
38
- "@tamagui/build": "1.134.5",
38
+ "@tamagui/build": "1.135.1",
39
39
  "react": "*"
40
40
  },
41
41
  "publishConfig": {
@@ -1,11 +1,41 @@
1
1
  import { isClient, useIsomorphicLayoutEffect } from '@tamagui/constants'
2
2
  import { isEqualShallow } from '@tamagui/is-equal-shallow'
3
- import { useCallback, type RefObject } from 'react'
3
+ import { createContext, useContext, useId, type ReactNode, type RefObject } from 'react'
4
4
 
5
5
  const LayoutHandlers = new WeakMap<HTMLElement, Function>()
6
+ const LayoutDisableKey = new WeakMap<HTMLElement, string>()
6
7
  const Nodes = new Set<HTMLElement>()
7
8
  const IntersectionState = new WeakMap<HTMLElement, boolean>()
8
9
 
10
+ // separating to avoid all re-rendering
11
+ const DisableLayoutContextValues: Record<string, boolean> = {}
12
+ const DisableLayoutContextKey = createContext<string>('')
13
+
14
+ const ENABLE = isClient && typeof IntersectionObserver !== 'undefined'
15
+
16
+ // internal testing - advanced helper to turn off layout measurement for extra performance
17
+ // TODO document!
18
+ // TODO could add frame skip control here
19
+ export const LayoutMeasurementController = ({
20
+ disable,
21
+ children,
22
+ }: {
23
+ disable: boolean
24
+ children: ReactNode
25
+ }): ReactNode => {
26
+ const id = useId()
27
+
28
+ useIsomorphicLayoutEffect(() => {
29
+ DisableLayoutContextValues[id] = disable
30
+ }, [disable, id])
31
+
32
+ return (
33
+ <DisableLayoutContextKey.Provider value={id}>
34
+ {children}
35
+ </DisableLayoutContextKey.Provider>
36
+ )
37
+ }
38
+
9
39
  // Single persistent IntersectionObserver for all nodes
10
40
  let globalIntersectionObserver: IntersectionObserver | null = null
11
41
 
@@ -39,11 +69,8 @@ export type LayoutEvent = {
39
69
  }
40
70
 
41
71
  const NodeRectCache = new WeakMap<HTMLElement, DOMRect>()
42
- const ParentRectCache = new WeakMap<HTMLElement, DOMRect>()
43
72
  const LastChangeTime = new WeakMap<HTMLElement, number>()
44
73
 
45
- const rAF = typeof window !== 'undefined' ? window.requestAnimationFrame : undefined
46
-
47
74
  // prevent thrashing during first hydration (somewhat, streaming gets trickier)
48
75
  let avoidUpdates = true
49
76
  const queuedUpdates = new Map<HTMLElement, Function>()
@@ -59,7 +86,7 @@ export function enable(): void {
59
86
  }
60
87
 
61
88
  function startGlobalObservers() {
62
- if (!isClient || globalIntersectionObserver) return
89
+ if (!ENABLE || globalIntersectionObserver) return
63
90
 
64
91
  globalIntersectionObserver = new IntersectionObserver(
65
92
  (entries) => {
@@ -76,134 +103,120 @@ function startGlobalObservers() {
76
103
  )
77
104
  }
78
105
 
79
- if (isClient) {
80
- if (rAF) {
81
- const supportsCheckVisibility = 'checkVisibility' in document.body
106
+ if (ENABLE) {
107
+ const BoundingRects = new WeakMap<any, DOMRectReadOnly | undefined>()
82
108
 
83
- const BoundingRects = new WeakMap<any, DOMRectReadOnly | undefined>()
109
+ async function updateLayoutIfChanged(node: HTMLElement) {
110
+ const onLayout = LayoutHandlers.get(node)
111
+ if (typeof onLayout !== 'function') return
84
112
 
85
- async function updateLayoutIfChanged(node: HTMLElement) {
86
- if (IntersectionState.get(node) === false) {
87
- // avoid due to not intersecting
88
- return
89
- }
90
- // triggers style recalculation in safari which is slower than not
91
- if (process.env.TAMAGUI_ONLAYOUT_VISIBILITY_CHECK === '1') {
92
- if (supportsCheckVisibility && !(node as any).checkVisibility()) {
93
- // avoid due to not visible
94
- return
95
- }
96
- }
113
+ const parentNode = node.parentElement
114
+ if (!parentNode) return
97
115
 
98
- const onLayout = LayoutHandlers.get(node)
99
- if (typeof onLayout !== 'function') return
116
+ let nodeRect: DOMRectReadOnly
117
+ let parentRect: DOMRectReadOnly
100
118
 
101
- const parentNode = node.parentElement
102
- if (!parentNode) return
119
+ if (strategy === 'async') {
120
+ const [nr, pr] = await Promise.all([
121
+ BoundingRects.get(node),
122
+ BoundingRects.get(parentNode),
123
+ ])
103
124
 
104
- let nodeRect: DOMRectReadOnly
105
- let parentRect: DOMRectReadOnly
125
+ if (!nr || !pr) {
126
+ return
127
+ }
106
128
 
107
- if (strategy === 'async') {
108
- const [nr, pr] = await Promise.all([
109
- BoundingRects.get(node) || getBoundingClientRectAsync(node),
110
- BoundingRects.get(parentNode) || getBoundingClientRectAsync(parentNode),
111
- ])
129
+ nodeRect = nr
130
+ parentRect = pr
131
+ } else {
132
+ nodeRect = node.getBoundingClientRect()
133
+ parentRect = parentNode.getBoundingClientRect()
134
+ }
112
135
 
113
- if (nr === false || pr === false) {
114
- return
115
- }
136
+ if (!nodeRect || !parentRect) {
137
+ return
138
+ }
116
139
 
117
- nodeRect = nr
118
- parentRect = pr
140
+ const cachedRect = NodeRectCache.get(node)
141
+ const cachedParentRect = NodeRectCache.get(parentNode)
142
+
143
+ if (
144
+ !cachedRect ||
145
+ !cachedParentRect ||
146
+ // has changed one rect
147
+ // @ts-expect-error DOMRectReadOnly can go into object
148
+ !isEqualShallow(cachedRect, nodeRect) ||
149
+ // @ts-expect-error DOMRectReadOnly can go into object
150
+ !isEqualShallow(cachedParentRect, parentRect)
151
+ ) {
152
+ NodeRectCache.set(node, nodeRect)
153
+ NodeRectCache.set(parentNode, parentRect)
154
+
155
+ const event = getElementLayoutEvent(nodeRect, parentRect)
156
+
157
+ if (avoidUpdates) {
158
+ queuedUpdates.set(node, () => onLayout(event))
119
159
  } else {
120
- nodeRect = node.getBoundingClientRect()
121
- parentRect = parentNode.getBoundingClientRect()
122
- }
123
-
124
- const cachedRect = NodeRectCache.get(node)
125
- const cachedParentRect = NodeRectCache.get(parentNode)
126
-
127
- if (
128
- !cachedRect ||
129
- // has changed one rect
130
- // @ts-expect-error DOMRectReadOnly can go into object
131
- (!isEqualShallow(cachedRect, nodeRect) &&
132
- // @ts-expect-error DOMRectReadOnly can go into object
133
- (!cachedParentRect || !isEqualShallow(cachedParentRect, parentRect)))
134
- ) {
135
- NodeRectCache.set(node, nodeRect)
136
- ParentRectCache.set(parentNode, parentRect)
137
-
138
- const event = getElementLayoutEvent(nodeRect, parentRect)
139
-
140
- if (avoidUpdates) {
141
- queuedUpdates.set(node, () => onLayout(event))
142
- } else {
143
- onLayout(event)
144
- }
160
+ onLayout(event)
145
161
  }
146
162
  }
163
+ }
147
164
 
148
- // note that getBoundingClientRect() does not thrash layout if its after an animation frame
149
- // ok new note: *if* it needed recalc then yea, but browsers often skip that, so it does
150
- // which is why we use async strategy in general
151
- rAF!(layoutOnAnimationFrame)
165
+ // note that getBoundingClientRect() does not thrash layout if its after an animation frame
166
+ // ok new note: *if* it needed recalc then yea, but browsers often skip that, so it does
167
+ // which is why we use async strategy in general
152
168
 
153
- // only run once in a few frames, this could be adjustable
154
- let frameCount = 0
169
+ const userSkipVal = process.env.TAMAGUI_LAYOUT_FRAME_SKIP
170
+ const RUN_EVERY_X_FRAMES = userSkipVal ? +userSkipVal : 14
155
171
 
156
- const userSkipVal = process.env.TAMAGUI_LAYOUT_FRAME_SKIP
157
- const RUN_EVERY_X_FRAMES = userSkipVal ? +userSkipVal : 10
172
+ async function layoutOnAnimationFrame() {
173
+ if (strategy !== 'off') {
174
+ const visibleNodes: HTMLElement[] = []
158
175
 
159
- async function layoutOnAnimationFrame() {
160
- if (strategy !== 'off') {
161
- if (!Nodes.size || frameCount++ % RUN_EVERY_X_FRAMES !== 0) {
162
- // skip a few frames to avoid work
163
- rAF!(layoutOnAnimationFrame)
164
- return
165
- }
176
+ // do a 1 rather than N IntersectionObservers for performance
177
+ const didRun = await new Promise<boolean>((res) => {
178
+ const io = new IntersectionObserver(
179
+ (entries) => {
180
+ io.disconnect()
181
+ for (const entry of entries) {
182
+ BoundingRects.set(entry.target, entry.boundingClientRect)
183
+ }
184
+ res(true)
185
+ },
186
+ {
187
+ threshold: 0,
188
+ }
189
+ )
166
190
 
167
- if (frameCount === Number.MAX_SAFE_INTEGER) {
168
- frameCount = 0
191
+ let didObserve = false
192
+
193
+ for (const node of Nodes) {
194
+ if (!(node.parentElement instanceof HTMLElement)) continue
195
+ const disableKey = LayoutDisableKey.get(node)
196
+ if (disableKey && DisableLayoutContextValues[disableKey] === true) continue
197
+ if (IntersectionState.get(node) === false) continue
198
+ didObserve = true
199
+ io.observe(node)
200
+ io.observe(node.parentElement)
201
+ visibleNodes.push(node)
169
202
  }
170
203
 
171
- // do a 1 rather than N IntersectionObservers for performance
172
- await new Promise<void>((res) => {
173
- const io = new IntersectionObserver(
174
- (entries) => {
175
- io.disconnect()
176
- for (const entry of entries) {
177
- BoundingRects.set(entry.target, entry.boundingClientRect)
178
- }
179
- res()
180
- },
181
- {
182
- threshold: 0,
183
- }
184
- )
185
- for (const node of Nodes) {
186
- if (node.parentElement instanceof HTMLElement) {
187
- io.observe(node)
188
- io.observe(node.parentElement)
189
- }
190
- }
191
- })
204
+ if (!didObserve) {
205
+ res(false)
206
+ }
207
+ })
192
208
 
193
- Nodes.forEach((node) => {
209
+ if (didRun) {
210
+ visibleNodes.forEach((node) => {
194
211
  updateLayoutIfChanged(node)
195
212
  })
196
213
  }
197
-
198
- rAF!(layoutOnAnimationFrame)
199
- }
200
- } else {
201
- if (process.env.NODE_ENV === 'development') {
202
- console.warn(
203
- `No requestAnimationFrame - please polyfill for onLayout to work correctly`
204
- )
205
214
  }
215
+
216
+ setTimeout(layoutOnAnimationFrame, 16.6667 * RUN_EVERY_X_FRAMES)
206
217
  }
218
+
219
+ layoutOnAnimationFrame()
207
220
  }
208
221
 
209
222
  export const getElementLayoutEvent = (
@@ -230,10 +243,13 @@ export function useElementLayout(
230
243
  ref: RefObject<TamaguiComponentStatePartial>,
231
244
  onLayout?: ((e: LayoutEvent) => void) | null
232
245
  ): void {
246
+ const disableKey = useContext(DisableLayoutContextKey)
247
+
233
248
  // ensure always up to date so we can avoid re-running effect
234
249
  const node = ensureWebElement(ref.current?.host)
235
250
  if (node && onLayout) {
236
251
  LayoutHandlers.set(node, onLayout)
252
+ LayoutDisableKey.set(node, disableKey)
237
253
  }
238
254
 
239
255
  useIsomorphicLayoutEffect(() => {
package/types/index.d.ts CHANGED
@@ -1,4 +1,11 @@
1
- import { type RefObject } from "react";
1
+ import { type ReactNode, type RefObject } from "react";
2
+ // internal testing - advanced helper to turn off layout measurement for extra performance
3
+ // TODO document!
4
+ // TODO could add frame skip control here
5
+ export declare const LayoutMeasurementController: ({ disable, children }: {
6
+ disable: boolean;
7
+ children: ReactNode;
8
+ }) => ReactNode;
2
9
  type TamaguiComponentStatePartial = {
3
10
  host?: any;
4
11
  };