@tamagui/core 1.126.13-1747813753833 → 1.126.13-1747874018127
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/hooks/useElementLayout.cjs +56 -63
- package/dist/cjs/hooks/useElementLayout.js +44 -61
- package/dist/cjs/hooks/useElementLayout.js.map +1 -1
- package/dist/cjs/hooks/useElementLayout.native.js +55 -94
- package/dist/cjs/hooks/useElementLayout.native.js.map +2 -2
- package/dist/cjs/index.cjs +4 -2
- package/dist/cjs/index.js +3 -2
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/index.native.js +4 -2
- package/dist/cjs/index.native.js.map +2 -2
- package/dist/esm/hooks/useElementLayout.js +48 -62
- package/dist/esm/hooks/useElementLayout.js.map +1 -1
- package/dist/esm/hooks/useElementLayout.mjs +57 -64
- package/dist/esm/hooks/useElementLayout.mjs.map +1 -1
- package/dist/esm/hooks/useElementLayout.native.js +72 -106
- package/dist/esm/hooks/useElementLayout.native.js.map +1 -1
- package/dist/esm/index.js +5 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.mjs +2 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +2 -1
- package/dist/esm/index.native.js.map +1 -1
- package/dist/native.js +85 -115
- package/dist/native.js.map +2 -2
- package/dist/test.native.js +85 -115
- package/dist/test.native.js.map +2 -2
- package/package.json +7 -7
- package/src/hooks/useElementLayout.tsx +87 -88
- package/src/index.tsx +6 -0
- package/types/hooks/useElementLayout.d.ts +2 -2
- package/types/hooks/useElementLayout.d.ts.map +1 -1
- package/types/index.d.ts +1 -0
- package/types/index.d.ts.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tamagui/core",
|
|
3
|
-
"version": "1.126.13-
|
|
3
|
+
"version": "1.126.13-1747874018127",
|
|
4
4
|
"source": "src/index.tsx",
|
|
5
5
|
"main": "dist/cjs",
|
|
6
6
|
"module": "dist/esm",
|
|
@@ -35,14 +35,14 @@
|
|
|
35
35
|
"native-test.d.ts"
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@tamagui/react-native-media-driver": "1.126.13-
|
|
39
|
-
"@tamagui/react-native-use-pressable": "1.126.13-
|
|
40
|
-
"@tamagui/react-native-use-responder-events": "1.126.13-
|
|
41
|
-
"@tamagui/use-event": "1.126.13-
|
|
42
|
-
"@tamagui/web": "1.126.13-
|
|
38
|
+
"@tamagui/react-native-media-driver": "1.126.13-1747874018127",
|
|
39
|
+
"@tamagui/react-native-use-pressable": "1.126.13-1747874018127",
|
|
40
|
+
"@tamagui/react-native-use-responder-events": "1.126.13-1747874018127",
|
|
41
|
+
"@tamagui/use-event": "1.126.13-1747874018127",
|
|
42
|
+
"@tamagui/web": "1.126.13-1747874018127"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@tamagui/build": "1.126.13-
|
|
45
|
+
"@tamagui/build": "1.126.13-1747874018127",
|
|
46
46
|
"@testing-library/react": "^16.1.0",
|
|
47
47
|
"csstype": "^3.0.10",
|
|
48
48
|
"typescript": "^5.8.2",
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import { useIsomorphicLayoutEffect } from '@tamagui/constants'
|
|
2
|
-
import
|
|
1
|
+
import { isClient, useIsomorphicLayoutEffect } from '@tamagui/constants'
|
|
2
|
+
import {
|
|
3
|
+
isEqualShallow,
|
|
4
|
+
type TamaguiComponentStateRef,
|
|
5
|
+
___onDidFinishClientRender,
|
|
6
|
+
} from '@tamagui/web'
|
|
3
7
|
import type { RefObject } from 'react'
|
|
4
|
-
import { getBoundingClientRect } from '../helpers/getBoundingClientRect'
|
|
5
8
|
|
|
6
|
-
const LayoutHandlers = new WeakMap<
|
|
7
|
-
const
|
|
9
|
+
const LayoutHandlers = new WeakMap<HTMLElement, Function>()
|
|
10
|
+
const Nodes = new Set<HTMLElement>()
|
|
8
11
|
|
|
9
12
|
export type LayoutValue = {
|
|
10
13
|
x: number
|
|
@@ -23,48 +26,78 @@ export type LayoutEvent = {
|
|
|
23
26
|
timeStamp: number
|
|
24
27
|
}
|
|
25
28
|
|
|
26
|
-
|
|
29
|
+
const NodeRectCache = new WeakMap<HTMLElement, DOMRect>()
|
|
30
|
+
const ParentRectCache = new WeakMap<HTMLElement, DOMRect>()
|
|
27
31
|
|
|
28
|
-
if (
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
if (isClient && typeof requestAnimationFrame === 'function') {
|
|
33
|
+
// prevent thrashing during first hydration (somewhat, streaming gets trickier)
|
|
34
|
+
let avoidUpdates = true
|
|
35
|
+
const queuedUpdates = new Map<HTMLElement, Function>()
|
|
36
|
+
|
|
37
|
+
___onDidFinishClientRender(() => {
|
|
38
|
+
avoidUpdates = false
|
|
39
|
+
if (queuedUpdates) {
|
|
40
|
+
queuedUpdates.forEach((cb) => cb())
|
|
41
|
+
queuedUpdates.clear()
|
|
37
42
|
}
|
|
38
43
|
})
|
|
39
44
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
function updateLayoutIfChanged(node: HTMLElement) {
|
|
46
|
+
const nodeRect = node.getBoundingClientRect()
|
|
47
|
+
const parentNode = node.parentElement
|
|
48
|
+
const parentRect = parentNode?.getBoundingClientRect()
|
|
49
|
+
|
|
50
|
+
const onLayout = LayoutHandlers.get(node)
|
|
51
|
+
if (typeof onLayout !== 'function') return
|
|
52
|
+
|
|
53
|
+
const cachedRect = NodeRectCache.get(node)
|
|
54
|
+
const cachedParentRect = parentNode ? NodeRectCache.get(parentNode) : null
|
|
55
|
+
|
|
56
|
+
if (
|
|
57
|
+
!cachedRect ||
|
|
58
|
+
// has changed one rect
|
|
59
|
+
(!isEqualShallow(cachedRect, nodeRect) &&
|
|
60
|
+
(!cachedParentRect || !isEqualShallow(cachedParentRect, parentRect)))
|
|
61
|
+
) {
|
|
62
|
+
NodeRectCache.set(node, nodeRect)
|
|
63
|
+
if (parentRect && parentNode) {
|
|
64
|
+
ParentRectCache.set(parentNode, parentRect)
|
|
65
|
+
}
|
|
66
|
+
const event = getElementLayoutEvent(node)
|
|
67
|
+
if (avoidUpdates) {
|
|
68
|
+
queuedUpdates.set(node, () => onLayout(event))
|
|
69
|
+
} else {
|
|
70
|
+
onLayout(event)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// note that getBoundingClientRect() does not thrash layout if its after an animation frame
|
|
76
|
+
requestAnimationFrame(layoutOnAnimationFrame)
|
|
77
|
+
function layoutOnAnimationFrame() {
|
|
78
|
+
Nodes.forEach(updateLayoutIfChanged)
|
|
79
|
+
requestAnimationFrame(layoutOnAnimationFrame)
|
|
49
80
|
}
|
|
50
81
|
}
|
|
51
82
|
|
|
52
|
-
export const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
})
|
|
83
|
+
export const getElementLayoutEvent = (target: HTMLElement): LayoutEvent => {
|
|
84
|
+
let res: LayoutEvent | null = null
|
|
85
|
+
measureLayout(target, null, (x, y, width, height, left, top) => {
|
|
86
|
+
res = {
|
|
87
|
+
nativeEvent: {
|
|
88
|
+
layout: { x, y, width, height, left, top },
|
|
89
|
+
target,
|
|
90
|
+
},
|
|
91
|
+
timeStamp: Date.now(),
|
|
92
|
+
}
|
|
63
93
|
})
|
|
94
|
+
if (!res) {
|
|
95
|
+
throw new Error(`‼️`) // impossible
|
|
96
|
+
}
|
|
97
|
+
return res
|
|
64
98
|
}
|
|
65
99
|
|
|
66
|
-
|
|
67
|
-
|
|
100
|
+
// matching old RN callback API (can we remove?)
|
|
68
101
|
export const measureLayout = (
|
|
69
102
|
node: HTMLElement,
|
|
70
103
|
relativeTo: HTMLElement | null,
|
|
@@ -77,22 +110,17 @@ export const measureLayout = (
|
|
|
77
110
|
top: number
|
|
78
111
|
) => void
|
|
79
112
|
) => {
|
|
80
|
-
const relativeNode = relativeTo || node?.
|
|
113
|
+
const relativeNode = relativeTo || node?.parentElement
|
|
81
114
|
if (relativeNode instanceof HTMLElement) {
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
relativeNodeDim
|
|
92
|
-
)
|
|
93
|
-
callback(x, y, width, height, left, top)
|
|
94
|
-
}
|
|
95
|
-
})
|
|
115
|
+
const nodeDim = node.getBoundingClientRect()
|
|
116
|
+
const relativeNodeDim = relativeNode.getBoundingClientRect()
|
|
117
|
+
if (relativeNodeDim && nodeDim) {
|
|
118
|
+
const { x, y, width, height, left, top } = getRelativeDimensions(
|
|
119
|
+
nodeDim,
|
|
120
|
+
relativeNodeDim
|
|
121
|
+
)
|
|
122
|
+
callback(x, y, width, height, left, top)
|
|
123
|
+
}
|
|
96
124
|
}
|
|
97
125
|
}
|
|
98
126
|
|
|
@@ -103,58 +131,29 @@ const getRelativeDimensions = (a: DOMRectReadOnly, b: DOMRectReadOnly) => {
|
|
|
103
131
|
return { x, y, width, height, left, top }
|
|
104
132
|
}
|
|
105
133
|
|
|
106
|
-
const getBoundingClientRectAsync = (
|
|
107
|
-
element: HTMLElement
|
|
108
|
-
): Promise<DOMRectReadOnly | undefined> => {
|
|
109
|
-
return new Promise((resolve) => {
|
|
110
|
-
function fallbackToSync() {
|
|
111
|
-
resolve(getBoundingClientRect(element))
|
|
112
|
-
}
|
|
113
|
-
const tm = setTimeout(fallbackToSync, 10)
|
|
114
|
-
const observer = new IntersectionObserver(
|
|
115
|
-
(entries, ob) => {
|
|
116
|
-
clearTimeout(tm)
|
|
117
|
-
ob.disconnect()
|
|
118
|
-
resolve(entries[0]?.boundingClientRect)
|
|
119
|
-
},
|
|
120
|
-
{
|
|
121
|
-
threshold: 0.0001,
|
|
122
|
-
}
|
|
123
|
-
)
|
|
124
|
-
observer.observe(element)
|
|
125
|
-
})
|
|
126
|
-
}
|
|
127
|
-
|
|
128
134
|
export function useElementLayout(
|
|
129
135
|
ref: RefObject<TamaguiComponentStateRef>,
|
|
130
136
|
onLayout?: ((e: LayoutEvent) => void) | null
|
|
131
137
|
) {
|
|
132
|
-
const node = ref.current?.host as Element
|
|
133
|
-
|
|
134
138
|
// ensure always up to date so we can avoid re-running effect
|
|
139
|
+
const node = ref.current?.host as HTMLElement
|
|
135
140
|
if (node && onLayout) {
|
|
136
141
|
LayoutHandlers.set(node, onLayout)
|
|
137
142
|
}
|
|
138
143
|
|
|
139
144
|
useIsomorphicLayoutEffect(() => {
|
|
140
|
-
if (!
|
|
141
|
-
const node = ref.current?.host as
|
|
145
|
+
if (!onLayout) return
|
|
146
|
+
const node = ref.current?.host as HTMLElement
|
|
142
147
|
if (!node) return
|
|
143
148
|
|
|
144
|
-
// setup once
|
|
145
149
|
LayoutHandlers.set(node, onLayout)
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
measureElement(node as HTMLElement).then(onLayout)
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
resizeListeners.add(onResize)
|
|
152
|
-
resizeObserver.observe(node)
|
|
150
|
+
Nodes.add(node)
|
|
151
|
+
onLayout(getElementLayoutEvent(node))
|
|
153
152
|
|
|
154
153
|
return () => {
|
|
154
|
+
Nodes.delete(node)
|
|
155
155
|
LayoutHandlers.delete(node)
|
|
156
|
-
|
|
157
|
-
resizeObserver?.unobserve(node)
|
|
156
|
+
NodeRectCache.delete(node)
|
|
158
157
|
}
|
|
159
158
|
}, [ref, !!onLayout])
|
|
160
159
|
}
|
package/src/index.tsx
CHANGED
|
@@ -29,6 +29,12 @@ import type { RNTextProps, RNViewProps } from './reactNativeTypes'
|
|
|
29
29
|
import { usePressability } from './vendor/Pressability'
|
|
30
30
|
import { addNativeValidStyles } from './addNativeValidStyles'
|
|
31
31
|
|
|
32
|
+
// helpful for usage outside of tamagui
|
|
33
|
+
export {
|
|
34
|
+
getElementLayoutEvent,
|
|
35
|
+
type LayoutEvent,
|
|
36
|
+
} from './hooks/useElementLayout'
|
|
37
|
+
|
|
32
38
|
// add newer style props based on react native version
|
|
33
39
|
addNativeValidStyles()
|
|
34
40
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type TamaguiComponentStateRef } from '@tamagui/web';
|
|
2
2
|
import type { RefObject } from 'react';
|
|
3
3
|
export type LayoutValue = {
|
|
4
4
|
x: number;
|
|
@@ -15,7 +15,7 @@ export type LayoutEvent = {
|
|
|
15
15
|
};
|
|
16
16
|
timeStamp: number;
|
|
17
17
|
};
|
|
18
|
-
export declare const
|
|
18
|
+
export declare const getElementLayoutEvent: (target: HTMLElement) => LayoutEvent;
|
|
19
19
|
export declare const measureLayout: (node: HTMLElement, relativeTo: HTMLElement | null, callback: (x: number, y: number, width: number, height: number, left: number, top: number) => void) => void;
|
|
20
20
|
export declare function useElementLayout(ref: RefObject<TamaguiComponentStateRef>, onLayout?: ((e: LayoutEvent) => void) | null): void;
|
|
21
21
|
//# sourceMappingURL=useElementLayout.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useElementLayout.d.ts","sourceRoot":"","sources":["../../src/hooks/useElementLayout.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"useElementLayout.d.ts","sourceRoot":"","sources":["../../src/hooks/useElementLayout.tsx"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,wBAAwB,EAE9B,MAAM,cAAc,CAAA;AACrB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAKtC,MAAM,MAAM,WAAW,GAAG;IACxB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,WAAW,EAAE;QACX,MAAM,EAAE,WAAW,CAAA;QACnB,MAAM,EAAE,GAAG,CAAA;KACZ,CAAA;IACD,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAwDD,eAAO,MAAM,qBAAqB,GAAI,QAAQ,WAAW,KAAG,WAe3D,CAAA;AAGD,eAAO,MAAM,aAAa,GACxB,MAAM,WAAW,EACjB,YAAY,WAAW,GAAG,IAAI,EAC9B,UAAU,CACR,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,KACR,IAAI,SAcV,CAAA;AASD,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,SAAS,CAAC,wBAAwB,CAAC,EACxC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,IAAI,QAuB7C"}
|
package/types/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { StackNonStyleProps, StackStyleBase, TamaDefer, TamaguiComponent, TamaguiElement, TamaguiTextElement, TextNonStyleProps, TextProps, TextStylePropsBase } from '@tamagui/web';
|
|
2
2
|
import { createTamagui as createTamaguiWeb } from '@tamagui/web';
|
|
3
3
|
import type { RNTextProps, RNViewProps } from './reactNativeTypes';
|
|
4
|
+
export { getElementLayoutEvent, type LayoutEvent, } from './hooks/useElementLayout';
|
|
4
5
|
type RNExclusiveViewProps = Omit<RNViewProps, keyof StackNonStyleProps>;
|
|
5
6
|
export interface RNTamaguiViewNonStyleProps extends StackNonStyleProps, RNExclusiveViewProps {
|
|
6
7
|
}
|
package/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,kBAAkB,EAClB,cAAc,EACd,SAAS,EACT,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EACjB,SAAS,EACT,kBAAkB,EACnB,MAAM,cAAc,CAAA;AACrB,OAAO,EAKL,aAAa,IAAI,gBAAgB,EAElC,MAAM,cAAc,CAAA;AAOrB,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,kBAAkB,EAClB,cAAc,EACd,SAAS,EACT,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EACjB,SAAS,EACT,kBAAkB,EACnB,MAAM,cAAc,CAAA;AACrB,OAAO,EAKL,aAAa,IAAI,gBAAgB,EAElC,MAAM,cAAc,CAAA;AAOrB,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAKlE,OAAO,EACL,qBAAqB,EACrB,KAAK,WAAW,GACjB,MAAM,0BAA0B,CAAA;AAOjC,KAAK,oBAAoB,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,kBAAkB,CAAC,CAAA;AACvE,MAAM,WAAW,0BACf,SAAQ,kBAAkB,EACxB,oBAAoB;CAAG;AAE3B,KAAK,aAAa,GAAG,gBAAgB,CACnC,SAAS,EACT,cAAc,EACd,0BAA0B,EAC1B,cAAc,EACd,EAAE,CACH,CAAA;AAED,KAAK,oBAAoB,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,SAAS,CAAC,CAAA;AAC9D,MAAM,WAAW,0BACf,SAAQ,iBAAiB,EACvB,oBAAoB;CAAG;AAE3B,KAAK,aAAa,GAAG,gBAAgB,CACnC,SAAS,EACT,kBAAkB,EAClB,0BAA0B,EAC1B,kBAAkB,EAClB,EAAE,CACH,CAAA;AAGD,cAAc,cAAc,CAAA;AAG5B,cAAc,oBAAoB,CAAA;AAGlC,eAAO,MAAM,aAAa,EAAE,OAAO,gBAOlC,CAAA;AAmLD,eAAO,MAAM,IAAI,EAAqB,aAAa,CAAA;AACnD,eAAO,MAAM,KAAK,EAAsB,aAAa,CAAA;AACrD,eAAO,MAAM,IAAI,EAAqB,aAAa,CAAA"}
|