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