@tamagui/use-element-layout 2.7.7 → 3.0.0-beta.643.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.
@@ -0,0 +1,415 @@
1
+ "use strict";
2
+
3
+
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all) __defProp(target, name, {
10
+ get: all[name],
11
+ enumerable: true
12
+ });
13
+ };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") {
16
+ for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
17
+ get: () => from[key],
18
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
19
+ });
20
+ }
21
+ return to;
22
+ };
23
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
24
+ var index_exports = {};
25
+ __export(index_exports, {
26
+ LayoutMeasurementController: () => LayoutMeasurementController,
27
+ createMeasure: () => createMeasure,
28
+ createMeasureInWindow: () => createMeasureInWindow,
29
+ createMeasureLayout: () => createMeasureLayout,
30
+ enable: () => enable,
31
+ getBoundingClientRectAsync: () => getBoundingClientRectAsync,
32
+ getElementLayoutEvent: () => getElementLayoutEvent,
33
+ measure: () => measure,
34
+ measureInWindow: () => measureInWindow,
35
+ measureLayout: () => measureLayout,
36
+ measureNode: () => measureNode,
37
+ registerLayoutNode: () => registerLayoutNode,
38
+ setOnLayoutStrategy: () => setOnLayoutStrategy,
39
+ useElementLayout: () => useElementLayout
40
+ });
41
+ module.exports = __toCommonJS(index_exports);
42
+ var import_jsx_runtime = require("react/jsx-runtime");
43
+ var import_constants = require("@tamagui/constants");
44
+ var import_react = require("react");
45
+ function _instanceof(left, right) {
46
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) return !!right[Symbol.hasInstance](left);
47
+ else return left instanceof right;
48
+ }
49
+ var LayoutHandlers = /* @__PURE__ */ new WeakMap();
50
+ var LayoutDisableKey = /* @__PURE__ */ new WeakMap();
51
+ var Nodes = /* @__PURE__ */ new Set();
52
+ var usePretransformDimensions = function() {
53
+ return globalThis.__TAMAGUI_ONLAYOUT_PRETRANSFORM === true || process.env.TAMAGUI_ONLAYOUT_PRETRANSFORM === "1";
54
+ };
55
+ var _debugLayout;
56
+ function isDebugLayout() {
57
+ if (_debugLayout === void 0) _debugLayout = typeof window !== "undefined" && new URLSearchParams(window.location.search).has("__tamaDebugLayout");
58
+ return _debugLayout;
59
+ }
60
+ var DisableLayoutContextValues = {};
61
+ var DisableLayoutContextKey = /* @__PURE__ */ (0, import_react.createContext)("");
62
+ var ENABLE = false;
63
+ var LayoutMeasurementController = function(param) {
64
+ var { disable, children } = param;
65
+ var id = (0, import_react.useId)();
66
+ (0, import_constants.useIsomorphicLayoutEffect)(function() {
67
+ var wasDisabled = DisableLayoutContextValues[id] === true;
68
+ DisableLayoutContextValues[id] = disable;
69
+ if (wasDisabled && !disable) measureOnNextFrame === null || measureOnNextFrame === void 0 || measureOnNextFrame();
70
+ }, [disable, id]);
71
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DisableLayoutContextKey.Provider, {
72
+ value: id,
73
+ children
74
+ });
75
+ };
76
+ var strategy = "async";
77
+ var resumeLayoutLoop;
78
+ var measureOnNextFrame;
79
+ function setOnLayoutStrategy(state) {
80
+ strategy = state;
81
+ resumeLayoutLoop === null || resumeLayoutLoop === void 0 || resumeLayoutLoop();
82
+ }
83
+ var NodeRectCache = /* @__PURE__ */ new WeakMap();
84
+ var avoidUpdates = true;
85
+ var queuedUpdates = /* @__PURE__ */ new Map();
86
+ function enable() {
87
+ if (avoidUpdates) {
88
+ avoidUpdates = false;
89
+ if (queuedUpdates) {
90
+ queuedUpdates.forEach(function(cb) {
91
+ return cb();
92
+ });
93
+ queuedUpdates.clear();
94
+ }
95
+ }
96
+ }
97
+ function rectsEqual(a, b) {
98
+ return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
99
+ }
100
+ if (ENABLE) {
101
+ let ensureRectFetchObserver2 = function() {
102
+ if (rectFetchObserver) return rectFetchObserver;
103
+ rectFetchObserver = new IntersectionObserver(function(entries) {
104
+ lastCallbackDelay = Math.round(performance.now() - rectFetchStartTime);
105
+ for (var i = 0; i < entries.length; i++) BoundingRects.set(entries[i].target, entries[i].boundingClientRect);
106
+ if (process.env.NODE_ENV === "development" && isDebugLayout() && lastCallbackDelay > 50) console.warn("[onLayout-io-delay]", lastCallbackDelay + "ms", entries.length, "entries");
107
+ if (rectFetchResolve) {
108
+ rectFetchResolve(true);
109
+ rectFetchResolve = null;
110
+ }
111
+ }, { threshold: 0 });
112
+ return rectFetchObserver;
113
+ }, scheduleLayoutFrame2 = function() {
114
+ if (frameScheduled || strategy === "off" || Nodes.size === 0 || document.hidden) return;
115
+ frameScheduled = true;
116
+ rAF ? rAF(layoutOnAnimationFrame) : setTimeout(layoutOnAnimationFrame, 16);
117
+ };
118
+ var BoundingRects = /* @__PURE__ */ new WeakMap();
119
+ var rectFetchObserver = null;
120
+ var rectFetchResolve = null;
121
+ var rectFetchStartTime = 0;
122
+ var lastCallbackDelay = 0;
123
+ async function updateLayoutIfChanged(node) {
124
+ if (typeof LayoutHandlers.get(node) !== "function") return;
125
+ var parentNode = node.parentElement;
126
+ if (!parentNode) return;
127
+ var nodeRect;
128
+ var parentRect;
129
+ if (strategy === "async") {
130
+ nodeRect = BoundingRects.get(node);
131
+ parentRect = BoundingRects.get(parentNode);
132
+ if (!nodeRect || !parentRect) return;
133
+ } else {
134
+ nodeRect = node.getBoundingClientRect();
135
+ parentRect = parentNode.getBoundingClientRect();
136
+ }
137
+ emitLayoutIfChanged(node, parentNode, nodeRect, parentRect);
138
+ }
139
+ var rAF = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : void 0;
140
+ var userSkipVal = process.env.TAMAGUI_LAYOUT_FRAME_SKIP;
141
+ var BASE_SKIP_FRAMES = userSkipVal ? +userSkipVal : 10;
142
+ var MAX_SKIP_FRAMES = 20;
143
+ var skipFrames = BASE_SKIP_FRAMES;
144
+ var frameCount = 0;
145
+ var frameScheduled = false;
146
+ async function layoutOnAnimationFrame() {
147
+ if (frameCount++ % skipFrames !== 0) {
148
+ frameScheduled = false;
149
+ scheduleLayoutFrame2();
150
+ return;
151
+ }
152
+ if (frameCount >= Number.MAX_SAFE_INTEGER) frameCount = 0;
153
+ if (strategy !== "off") {
154
+ var activeNodes = [];
155
+ var parentsToObserve = /* @__PURE__ */ new Set();
156
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
157
+ try {
158
+ for (var _iterator = Nodes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
159
+ var node = _step.value;
160
+ var parentElement = node.parentElement;
161
+ if (!_instanceof(parentElement, HTMLElement)) {
162
+ cleanupNode(node);
163
+ continue;
164
+ }
165
+ var disableKey = LayoutDisableKey.get(node);
166
+ if (disableKey && DisableLayoutContextValues[disableKey] === true) continue;
167
+ activeNodes.push(node);
168
+ parentsToObserve.add(parentElement);
169
+ }
170
+ } catch (err) {
171
+ _didIteratorError = true;
172
+ _iteratorError = err;
173
+ } finally {
174
+ try {
175
+ if (!_iteratorNormalCompletion && _iterator.return != null) _iterator.return();
176
+ } finally {
177
+ if (_didIteratorError) throw _iteratorError;
178
+ }
179
+ }
180
+ if (activeNodes.length > 0) {
181
+ var io = ensureRectFetchObserver2();
182
+ rectFetchStartTime = performance.now();
183
+ for (var i = 0; i < activeNodes.length; i++) io.observe(activeNodes[i]);
184
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = void 0;
185
+ try {
186
+ for (var _iterator1 = parentsToObserve[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true) {
187
+ var parent = _step1.value;
188
+ io.observe(parent);
189
+ }
190
+ } catch (err) {
191
+ _didIteratorError1 = true;
192
+ _iteratorError1 = err;
193
+ } finally {
194
+ try {
195
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) _iterator1.return();
196
+ } finally {
197
+ if (_didIteratorError1) throw _iteratorError1;
198
+ }
199
+ }
200
+ await new Promise(function(res) {
201
+ rectFetchResolve = res;
202
+ });
203
+ for (var i1 = 0; i1 < activeNodes.length; i1++) io.unobserve(activeNodes[i1]);
204
+ var _iteratorNormalCompletion2 = true, _didIteratorError2 = false, _iteratorError2 = void 0;
205
+ try {
206
+ for (var _iterator2 = parentsToObserve[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
207
+ var parent1 = _step2.value;
208
+ io.unobserve(parent1);
209
+ }
210
+ } catch (err) {
211
+ _didIteratorError2 = true;
212
+ _iteratorError2 = err;
213
+ } finally {
214
+ try {
215
+ if (!_iteratorNormalCompletion2 && _iterator2.return != null) _iterator2.return();
216
+ } finally {
217
+ if (_didIteratorError2) throw _iteratorError2;
218
+ }
219
+ }
220
+ if (lastCallbackDelay > 50) skipFrames = Math.min(skipFrames + 2, MAX_SKIP_FRAMES);
221
+ else if (lastCallbackDelay < 20) skipFrames = Math.max(skipFrames - 1, BASE_SKIP_FRAMES);
222
+ for (var i2 = 0; i2 < activeNodes.length; i2++) updateLayoutIfChanged(activeNodes[i2]);
223
+ }
224
+ }
225
+ frameScheduled = false;
226
+ scheduleLayoutFrame2();
227
+ }
228
+ resumeLayoutLoop = scheduleLayoutFrame2;
229
+ measureOnNextFrame = function() {
230
+ frameCount = 0;
231
+ scheduleLayoutFrame2();
232
+ };
233
+ document.addEventListener("visibilitychange", scheduleLayoutFrame2);
234
+ scheduleLayoutFrame2();
235
+ }
236
+ var getElementLayoutEvent = function(nodeRect, parentRect, node) {
237
+ return {
238
+ nativeEvent: {
239
+ layout: getRelativeDimensions(nodeRect, parentRect, node),
240
+ target: nodeRect
241
+ },
242
+ timeStamp: Date.now()
243
+ };
244
+ };
245
+ var getPreTransformDimensions = function(node) {
246
+ return {
247
+ width: node.offsetWidth,
248
+ height: node.offsetHeight
249
+ };
250
+ };
251
+ var getRelativeDimensions = function(a, b, aNode) {
252
+ var { left, top } = a;
253
+ var x = left - b.left;
254
+ var y = top - b.top;
255
+ var { width, height } = usePretransformDimensions() && aNode ? getPreTransformDimensions(aNode) : {
256
+ width: a.width,
257
+ height: a.height
258
+ };
259
+ return {
260
+ x,
261
+ y,
262
+ width,
263
+ height,
264
+ pageX: a.left,
265
+ pageY: a.top
266
+ };
267
+ };
268
+ function emitLayoutIfChanged(node, parentNode, nodeRect, parentRect) {
269
+ var onLayout = LayoutHandlers.get(node);
270
+ if (typeof onLayout !== "function") return;
271
+ var cachedRect = NodeRectCache.get(node);
272
+ var cachedParentRect = NodeRectCache.get(parentNode);
273
+ var nodeChanged = !cachedRect || !rectsEqual(cachedRect, nodeRect);
274
+ var parentChanged = !cachedParentRect || !rectsEqual(cachedParentRect, parentRect);
275
+ if (!nodeChanged && !parentChanged) return;
276
+ NodeRectCache.set(node, nodeRect);
277
+ NodeRectCache.set(parentNode, parentRect);
278
+ var event = getElementLayoutEvent(nodeRect, parentRect, node);
279
+ if (process.env.NODE_ENV === "development" && isDebugLayout()) console.log("[useElementLayout] change", {
280
+ tag: node.tagName,
281
+ id: node.id || void 0,
282
+ className: (node.className || "").slice(0, 60) || void 0,
283
+ layout: event.nativeEvent.layout,
284
+ first: !cachedRect
285
+ });
286
+ if (avoidUpdates) queuedUpdates.set(node, function() {
287
+ return onLayout(event);
288
+ });
289
+ else onLayout(event);
290
+ }
291
+ function observeLayoutNode(node, disableKey) {
292
+ Nodes.add(node);
293
+ if (disableKey) LayoutDisableKey.set(node, disableKey);
294
+ else LayoutDisableKey.delete(node);
295
+ resumeLayoutLoop === null || resumeLayoutLoop === void 0 || resumeLayoutLoop();
296
+ }
297
+ function registerLayoutNode(node, onChange, disableKey) {
298
+ LayoutHandlers.set(node, onChange);
299
+ observeLayoutNode(node, disableKey);
300
+ return function() {
301
+ return cleanupNode(node);
302
+ };
303
+ }
304
+ function cleanupNode(node) {
305
+ Nodes.delete(node);
306
+ LayoutHandlers.delete(node);
307
+ LayoutDisableKey.delete(node);
308
+ NodeRectCache.delete(node);
309
+ }
310
+ var PrevHostNode = /* @__PURE__ */ new WeakMap();
311
+ function emitLayoutSync(node) {
312
+ var onLayout = LayoutHandlers.get(node);
313
+ if (typeof onLayout !== "function") return;
314
+ var parentNode = node.parentElement;
315
+ if (!parentNode) return;
316
+ var nodeRect = node.getBoundingClientRect();
317
+ var parentRect = parentNode.getBoundingClientRect();
318
+ NodeRectCache.set(node, nodeRect);
319
+ NodeRectCache.set(parentNode, parentRect);
320
+ onLayout(getElementLayoutEvent(nodeRect, parentRect, node));
321
+ }
322
+ function useElementLayout(ref, onLayout) {
323
+ var _ref_current;
324
+ var disableKey = (0, import_react.useContext)(DisableLayoutContextKey);
325
+ var node = ensureWebElement((_ref_current = ref.current) === null || _ref_current === void 0 ? void 0 : _ref_current.host);
326
+ if (node && onLayout) {
327
+ LayoutHandlers.set(node, onLayout);
328
+ LayoutDisableKey.set(node, disableKey);
329
+ }
330
+ (0, import_constants.useIsomorphicLayoutEffect)(function() {
331
+ var _ref_current2;
332
+ if (!onLayout) return;
333
+ var nextNode = ensureWebElement((_ref_current2 = ref.current) === null || _ref_current2 === void 0 ? void 0 : _ref_current2.host);
334
+ var prevNode = PrevHostNode.get(ref);
335
+ if (nextNode === prevNode) return;
336
+ if (prevNode) cleanupNode(prevNode);
337
+ PrevHostNode.set(ref, nextNode);
338
+ if (!nextNode) return;
339
+ LayoutHandlers.set(nextNode, onLayout);
340
+ observeLayoutNode(nextNode, disableKey);
341
+ emitLayoutSync(nextNode);
342
+ });
343
+ (0, import_constants.useIsomorphicLayoutEffect)(function() {
344
+ var _ref_current2;
345
+ if (!onLayout) return;
346
+ var node2 = (_ref_current2 = ref.current) === null || _ref_current2 === void 0 ? void 0 : _ref_current2.host;
347
+ if (!node2) return;
348
+ LayoutHandlers.set(node2, onLayout);
349
+ observeLayoutNode(node2, disableKey);
350
+ if (process.env.NODE_ENV === "development" && isDebugLayout()) console.log("[useElementLayout] register", {
351
+ tag: node2.tagName,
352
+ id: node2.id || void 0,
353
+ className: (node2.className || "").slice(0, 60) || void 0,
354
+ totalNodes: Nodes.size
355
+ });
356
+ return function() {
357
+ cleanupNode(node2);
358
+ var swappedNode = PrevHostNode.get(ref);
359
+ if (swappedNode && swappedNode !== node2) cleanupNode(swappedNode);
360
+ PrevHostNode.delete(ref);
361
+ };
362
+ }, [ref, !!onLayout]);
363
+ }
364
+ function ensureWebElement(x) {
365
+ if (typeof HTMLElement === "undefined") return;
366
+ return _instanceof(x, HTMLElement) ? x : void 0;
367
+ }
368
+ var getBoundingClientRectAsync = function(node) {
369
+ return new Promise(function(res) {
370
+ if (!node || node.nodeType !== 1) return res(false);
371
+ var io = new IntersectionObserver(function(entries) {
372
+ io.disconnect();
373
+ return res(entries[0].boundingClientRect);
374
+ }, { threshold: 0 });
375
+ io.observe(node);
376
+ });
377
+ };
378
+ var measureNode = async function(node, relativeTo) {
379
+ var relativeNode = relativeTo || (node === null || node === void 0 ? void 0 : node.parentElement);
380
+ if (_instanceof(relativeNode, HTMLElement)) {
381
+ var [nodeDim, relativeNodeDim] = await Promise.all([getBoundingClientRectAsync(node), getBoundingClientRectAsync(relativeNode)]);
382
+ if (relativeNodeDim && nodeDim) return getRelativeDimensions(nodeDim, relativeNodeDim, node);
383
+ }
384
+ return null;
385
+ };
386
+ var measure = async function(node, callback) {
387
+ var out = await measureNode(node, _instanceof(node.parentNode, HTMLElement) ? node.parentNode : null);
388
+ if (out) callback === null || callback === void 0 || callback(out.x, out.y, out.width, out.height, out.pageX, out.pageY);
389
+ return out;
390
+ };
391
+ function createMeasure(node) {
392
+ return function(callback) {
393
+ return measure(node, callback);
394
+ };
395
+ }
396
+ var measureInWindow = async function(node, callback) {
397
+ var out = await measureNode(node, null);
398
+ if (out) callback === null || callback === void 0 || callback(out.pageX, out.pageY, out.width, out.height);
399
+ return out;
400
+ };
401
+ var createMeasureInWindow = function(node) {
402
+ return function(callback) {
403
+ return measureInWindow(node, callback);
404
+ };
405
+ };
406
+ var measureLayout = async function(node, relativeNode, callback) {
407
+ var out = await measureNode(node, relativeNode);
408
+ if (out) callback === null || callback === void 0 || callback(out.x, out.y, out.width, out.height, out.pageX, out.pageY);
409
+ return out;
410
+ };
411
+ function createMeasureLayout(node) {
412
+ return function(relativeTo, callback) {
413
+ return measureLayout(node, relativeTo, callback);
414
+ };
415
+ }