react-native-unistyles 3.4.0 → 3.5.0
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/README.md +23 -7
- package/android/build.gradle +12 -1
- package/android/src/main/cxx/NativeUnistylesModule.cpp +8 -4
- package/android/src/main/cxx/NativeUnistylesModule.h +5 -1
- package/components/native/ActivityIndicator/package.json +1 -1
- package/cxx/common/UnistylesConstants.h +1 -0
- package/cxx/converters/TransformOriginConverter.cpp +106 -0
- package/cxx/core/StyleSheetRegistry.cpp +9 -9
- package/cxx/core/StyleSheetRegistry.h +3 -3
- package/cxx/core/UnistyleWrapper.h +13 -1
- package/cxx/core/UnistylesRegistry.cpp +102 -18
- package/cxx/core/UnistylesRegistry.h +42 -5
- package/cxx/hybridObjects/HybridShadowRegistry.cpp +124 -4
- package/cxx/hybridObjects/HybridShadowRegistry.h +20 -0
- package/cxx/hybridObjects/HybridStyleSheet.cpp +20 -12
- package/cxx/hybridObjects/HybridUnistylesRuntime.cpp +11 -1
- package/cxx/hybridObjects/HybridUnistylesRuntime.h +4 -2
- package/cxx/parser/Parser.cpp +29 -1
- package/cxx/parser/Parser.h +1 -0
- package/cxx/shadowTree/NativeProps.h +46 -2
- package/cxx/shadowTree/ShadowTrafficController.h +4 -0
- package/cxx/shadowTree/ShadowTreeDiagnostics.cpp +339 -0
- package/cxx/shadowTree/ShadowTreeDiagnostics.h +18 -0
- package/cxx/shadowTree/ShadowTreeManager.cpp +7 -1
- package/cxx/shadowTree/ShadowTreeManager.h +1 -1
- package/diagnostics/package.json +6 -0
- package/ios/UnistylesModuleOnLoad.mm +9 -3
- package/lib/commonjs/components/native/ActivityIndicator.native.js +10 -0
- package/lib/commonjs/components/native/ActivityIndicator.native.js.map +1 -0
- package/lib/commonjs/components/native/NativeText.js +6 -0
- package/lib/commonjs/components/native/NativeText.js.map +1 -1
- package/lib/commonjs/components/native/NativeText.native.js +17 -1
- package/lib/commonjs/components/native/NativeText.native.js.map +1 -1
- package/lib/commonjs/components/native/NativeView.js +6 -0
- package/lib/commonjs/components/native/NativeView.js.map +1 -1
- package/lib/commonjs/components/native/NativeView.native.js +22 -3
- package/lib/commonjs/components/native/NativeView.native.js.map +1 -1
- package/lib/commonjs/components/native/Pressable.js +7 -3
- package/lib/commonjs/components/native/Pressable.js.map +1 -1
- package/lib/commonjs/components/native/TouchableHighlight.native.js +10 -0
- package/lib/commonjs/components/native/TouchableHighlight.native.js.map +1 -0
- package/lib/commonjs/core/createUnistylesActivityIndicator.js +41 -0
- package/lib/commonjs/core/createUnistylesActivityIndicator.js.map +1 -0
- package/lib/commonjs/core/createUnistylesElement.js +59 -14
- package/lib/commonjs/core/createUnistylesElement.js.map +1 -1
- package/lib/commonjs/core/createUnistylesTouchableHighlight.js +58 -0
- package/lib/commonjs/core/createUnistylesTouchableHighlight.js.map +1 -0
- package/lib/commonjs/core/index.js +14 -0
- package/lib/commonjs/core/index.js.map +1 -1
- package/lib/commonjs/diagnostics/index.js +13 -0
- package/lib/commonjs/diagnostics/index.js.map +1 -0
- package/lib/commonjs/diagnostics/types.js +2 -0
- package/lib/commonjs/diagnostics/types.js.map +1 -0
- package/lib/commonjs/diagnostics/verify.js +19 -0
- package/lib/commonjs/diagnostics/verify.js.map +1 -0
- package/lib/commonjs/diagnostics/verify.native.js +12 -0
- package/lib/commonjs/diagnostics/verify.native.js.map +1 -0
- package/lib/commonjs/index.js +38 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/mocks.js +41 -0
- package/lib/commonjs/mocks.js.map +1 -1
- package/lib/commonjs/reanimated/variant/useUpdateVariantColor.native.js +8 -0
- package/lib/commonjs/reanimated/variant/useUpdateVariantColor.native.js.map +1 -1
- package/lib/commonjs/specs/ShadowRegistry/index.js +97 -1
- package/lib/commonjs/specs/ShadowRegistry/index.js.map +1 -1
- package/lib/commonjs/specs/StyleSheet/index.js +5 -1
- package/lib/commonjs/specs/StyleSheet/index.js.map +1 -1
- package/lib/commonjs/specs/UnistylesRuntime/index.js.map +1 -1
- package/lib/commonjs/web/registry.js +3 -0
- package/lib/commonjs/web/registry.js.map +1 -1
- package/lib/module/components/native/ActivityIndicator.native.js +6 -0
- package/lib/module/components/native/ActivityIndicator.native.js.map +1 -0
- package/lib/module/components/native/NativeText.js +1 -1
- package/lib/module/components/native/NativeText.js.map +1 -1
- package/lib/module/components/native/NativeText.native.js +15 -1
- package/lib/module/components/native/NativeText.native.js.map +1 -1
- package/lib/module/components/native/NativeView.js +1 -0
- package/lib/module/components/native/NativeView.js.map +1 -1
- package/lib/module/components/native/NativeView.native.js +19 -2
- package/lib/module/components/native/NativeView.native.js.map +1 -1
- package/lib/module/components/native/Pressable.js +7 -3
- package/lib/module/components/native/Pressable.js.map +1 -1
- package/lib/module/components/native/TouchableHighlight.native.js +6 -0
- package/lib/module/components/native/TouchableHighlight.native.js.map +1 -0
- package/lib/module/core/createUnistylesActivityIndicator.js +35 -0
- package/lib/module/core/createUnistylesActivityIndicator.js.map +1 -0
- package/lib/module/core/createUnistylesElement.js +58 -13
- package/lib/module/core/createUnistylesElement.js.map +1 -1
- package/lib/module/core/createUnistylesTouchableHighlight.js +52 -0
- package/lib/module/core/createUnistylesTouchableHighlight.js.map +1 -0
- package/lib/module/core/index.js +2 -0
- package/lib/module/core/index.js.map +1 -1
- package/lib/module/diagnostics/index.js +5 -0
- package/lib/module/diagnostics/index.js.map +1 -0
- package/lib/module/diagnostics/types.js +2 -0
- package/lib/module/diagnostics/types.js.map +1 -0
- package/lib/module/diagnostics/verify.js +14 -0
- package/lib/module/diagnostics/verify.js.map +1 -0
- package/lib/module/diagnostics/verify.native.js +8 -0
- package/lib/module/diagnostics/verify.native.js.map +1 -0
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/mocks.js +41 -0
- package/lib/module/mocks.js.map +1 -1
- package/lib/module/reanimated/variant/useUpdateVariantColor.native.js +9 -1
- package/lib/module/reanimated/variant/useUpdateVariantColor.native.js.map +1 -1
- package/lib/module/specs/ShadowRegistry/index.js +97 -1
- package/lib/module/specs/ShadowRegistry/index.js.map +1 -1
- package/lib/module/specs/StyleSheet/index.js +6 -1
- package/lib/module/specs/StyleSheet/index.js.map +1 -1
- package/lib/module/specs/UnistylesRuntime/index.js.map +1 -1
- package/lib/module/web/registry.js +3 -0
- package/lib/module/web/registry.js.map +1 -1
- package/lib/typescript/src/components/native/ActivityIndicator.native.d.ts +2 -0
- package/lib/typescript/src/components/native/ActivityIndicator.native.d.ts.map +1 -0
- package/lib/typescript/src/components/native/NativeText.d.ts +1 -1
- package/lib/typescript/src/components/native/NativeText.d.ts.map +1 -1
- package/lib/typescript/src/components/native/NativeText.native.d.ts.map +1 -1
- package/lib/typescript/src/components/native/NativeView.d.ts +1 -0
- package/lib/typescript/src/components/native/NativeView.d.ts.map +1 -1
- package/lib/typescript/src/components/native/NativeView.native.d.ts +2 -2
- package/lib/typescript/src/components/native/NativeView.native.d.ts.map +1 -1
- package/lib/typescript/src/components/native/Pressable.d.ts.map +1 -1
- package/lib/typescript/src/components/native/TouchableHighlight.native.d.ts +2 -0
- package/lib/typescript/src/components/native/TouchableHighlight.native.d.ts.map +1 -0
- package/lib/typescript/src/core/createUnistylesActivityIndicator.d.ts +3 -0
- package/lib/typescript/src/core/createUnistylesActivityIndicator.d.ts.map +1 -0
- package/lib/typescript/src/core/createUnistylesElement.d.ts.map +1 -1
- package/lib/typescript/src/core/createUnistylesTouchableHighlight.d.ts +3 -0
- package/lib/typescript/src/core/createUnistylesTouchableHighlight.d.ts.map +1 -0
- package/lib/typescript/src/core/index.d.ts +2 -0
- package/lib/typescript/src/core/index.d.ts.map +1 -1
- package/lib/typescript/src/core/useUnistyles.d.ts +1 -1
- package/lib/typescript/src/diagnostics/index.d.ts +3 -0
- package/lib/typescript/src/diagnostics/index.d.ts.map +1 -0
- package/lib/typescript/src/diagnostics/types.d.ts +19 -0
- package/lib/typescript/src/diagnostics/types.d.ts.map +1 -0
- package/lib/typescript/src/diagnostics/verify.d.ts +3 -0
- package/lib/typescript/src/diagnostics/verify.d.ts.map +1 -0
- package/lib/typescript/src/diagnostics/verify.native.d.ts +3 -0
- package/lib/typescript/src/diagnostics/verify.native.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +4 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/reanimated/variant/useUpdateVariantColor.native.d.ts.map +1 -1
- package/lib/typescript/src/specs/ShadowRegistry/index.d.ts +5 -1
- package/lib/typescript/src/specs/ShadowRegistry/index.d.ts.map +1 -1
- package/lib/typescript/src/specs/ShadowRegistry/types.d.ts +3 -0
- package/lib/typescript/src/specs/ShadowRegistry/types.d.ts.map +1 -1
- package/lib/typescript/src/specs/StyleSheet/index.d.ts +4 -1
- package/lib/typescript/src/specs/StyleSheet/index.d.ts.map +1 -1
- package/lib/typescript/src/specs/UnistylesRuntime/index.d.ts +2 -2
- package/lib/typescript/src/specs/UnistylesRuntime/index.d.ts.map +1 -1
- package/lib/typescript/src/types/breakpoints.d.ts +1 -1
- package/lib/typescript/src/types/breakpoints.d.ts.map +1 -1
- package/lib/typescript/src/types/stylesheet.d.ts +3 -3
- package/lib/typescript/src/types/stylesheet.d.ts.map +1 -1
- package/lib/typescript/src/web/registry.d.ts.map +1 -1
- package/package.json +9 -1
- package/plugin/index.d.ts +4 -4
- package/plugin/index.js +21 -5
- package/src/components/native/ActivityIndicator.native.tsx +5 -0
- package/src/components/native/NativeText.native.tsx +18 -1
- package/src/components/native/NativeText.tsx +1 -1
- package/src/components/native/NativeView.native.tsx +22 -2
- package/src/components/native/NativeView.tsx +2 -0
- package/src/components/native/Pressable.tsx +8 -3
- package/src/components/native/TouchableHighlight.native.tsx +5 -0
- package/src/core/createUnistylesActivityIndicator.tsx +47 -0
- package/src/core/createUnistylesElement.tsx +45 -14
- package/src/core/createUnistylesTouchableHighlight.tsx +69 -0
- package/src/core/index.ts +2 -0
- package/src/diagnostics/index.ts +3 -0
- package/src/diagnostics/types.ts +25 -0
- package/src/diagnostics/verify.native.ts +7 -0
- package/src/diagnostics/verify.ts +13 -0
- package/src/index.ts +4 -1
- package/src/mocks.ts +41 -0
- package/src/reanimated/variant/useUpdateVariantColor.native.ts +7 -1
- package/src/specs/ShadowRegistry/index.ts +128 -1
- package/src/specs/ShadowRegistry/types.ts +3 -0
- package/src/specs/StyleSheet/index.ts +10 -2
- package/src/specs/UnistylesRuntime/index.ts +7 -2
- package/src/types/breakpoints.ts +5 -3
- package/src/types/stylesheet.ts +3 -3
- package/src/web/registry.ts +3 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { TouchableHighlight } from 'react-native'
|
|
2
|
+
|
|
3
|
+
import React, { useCallback, useLayoutEffect, useRef, useState } from 'react'
|
|
4
|
+
|
|
5
|
+
import { UnistylesShadowRegistry } from '../specs'
|
|
6
|
+
import { copyComponentProperties } from '../utils'
|
|
7
|
+
import { passForwardedRef } from './passForwardRef'
|
|
8
|
+
import { maybeWarnAboutMultipleUnistyles } from './warn'
|
|
9
|
+
|
|
10
|
+
export const createUnistylesTouchableHighlight = (Component: typeof TouchableHighlight) => {
|
|
11
|
+
const UnistylesTouchableHighlight = (props: any) => {
|
|
12
|
+
const relinkRef = useRef<() => void>(undefined)
|
|
13
|
+
const [hiddenUnderlays, setHiddenUnderlays] = useState(0)
|
|
14
|
+
|
|
15
|
+
useLayoutEffect(() => {
|
|
16
|
+
if (hiddenUnderlays > 0) {
|
|
17
|
+
relinkRef.current?.()
|
|
18
|
+
}
|
|
19
|
+
}, [hiddenUnderlays])
|
|
20
|
+
|
|
21
|
+
// new props come with a parent render, re-renders for the underlay keep the ref and the scoped theme it captured
|
|
22
|
+
const ref = useCallback(
|
|
23
|
+
(ref: unknown) => {
|
|
24
|
+
maybeWarnAboutMultipleUnistyles(props.style, 'TouchableHighlight')
|
|
25
|
+
|
|
26
|
+
const scopedTheme = UnistylesShadowRegistry.getScopedTheme()
|
|
27
|
+
|
|
28
|
+
relinkRef.current = () => {
|
|
29
|
+
const previousScopedTheme = UnistylesShadowRegistry.getScopedTheme()
|
|
30
|
+
|
|
31
|
+
UnistylesShadowRegistry.setScopedTheme(scopedTheme)
|
|
32
|
+
// @ts-ignore this is hidden from TS
|
|
33
|
+
UnistylesShadowRegistry.remove(ref)
|
|
34
|
+
// @ts-ignore this is hidden from TS
|
|
35
|
+
UnistylesShadowRegistry.add(ref, props.style)
|
|
36
|
+
UnistylesShadowRegistry.setScopedTheme(previousScopedTheme)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return passForwardedRef(
|
|
40
|
+
ref,
|
|
41
|
+
props.ref,
|
|
42
|
+
() => {
|
|
43
|
+
// @ts-ignore this is hidden from TS
|
|
44
|
+
UnistylesShadowRegistry.add(ref, props.style)
|
|
45
|
+
},
|
|
46
|
+
() => {
|
|
47
|
+
relinkRef.current = undefined
|
|
48
|
+
// @ts-ignore this is hidden from TS
|
|
49
|
+
UnistylesShadowRegistry.remove(ref)
|
|
50
|
+
},
|
|
51
|
+
)
|
|
52
|
+
},
|
|
53
|
+
[props],
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<Component
|
|
58
|
+
{...props}
|
|
59
|
+
ref={ref}
|
|
60
|
+
onHideUnderlay={() => {
|
|
61
|
+
setHiddenUnderlays((count) => count + 1)
|
|
62
|
+
props.onHideUnderlay?.()
|
|
63
|
+
}}
|
|
64
|
+
/>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return copyComponentProperties(Component, UnistylesTouchableHighlight)
|
|
69
|
+
}
|
package/src/core/index.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { createUnistylesElement } from './createUnistylesElement'
|
|
2
|
+
export { createUnistylesActivityIndicator } from './createUnistylesActivityIndicator'
|
|
2
3
|
export { createUnistylesImageBackground } from './createUnistylesImageBackground'
|
|
4
|
+
export { createUnistylesTouchableHighlight } from './createUnistylesTouchableHighlight'
|
|
3
5
|
export { withUnistyles } from './withUnistyles'
|
|
4
6
|
export { passForwardedRef } from './passForwardRef'
|
|
5
7
|
export { getClassName } from './getClassname'
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type VerifyMismatch = {
|
|
2
|
+
tag: number
|
|
3
|
+
component: string
|
|
4
|
+
styleKey: string
|
|
5
|
+
prop: string
|
|
6
|
+
expected: string
|
|
7
|
+
actual: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type VerifyReport = {
|
|
11
|
+
// all nodes linked with Unistyles
|
|
12
|
+
linked: number
|
|
13
|
+
// nodes compared with the committed shadow tree
|
|
14
|
+
checked: number
|
|
15
|
+
// linked nodes that are not part of the committed shadow tree
|
|
16
|
+
detached: number
|
|
17
|
+
// nodes hidden by Suspense or frozen screens
|
|
18
|
+
suspended: number
|
|
19
|
+
// nodes unmounted without unlink, waiting for the sweep
|
|
20
|
+
orphans: number
|
|
21
|
+
// shadow tree updates that were not committed yet
|
|
22
|
+
pendingUpdates: number
|
|
23
|
+
mismatches: Array<VerifyMismatch>
|
|
24
|
+
errors: Array<string>
|
|
25
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { VerifyReport } from './types'
|
|
2
|
+
|
|
3
|
+
import { UnistylesShadowRegistry } from '../specs'
|
|
4
|
+
|
|
5
|
+
// Compares props committed to the shadow tree with styles rebuilt for every linked node
|
|
6
|
+
// (its own arguments, variants and the current theme). Meant for tests, it never commits anything.
|
|
7
|
+
export const verify = (): VerifyReport => UnistylesShadowRegistry.verify()
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { VerifyReport } from './types'
|
|
2
|
+
|
|
3
|
+
// There is no shadow tree on web
|
|
4
|
+
export const verify = (): VerifyReport => ({
|
|
5
|
+
linked: 0,
|
|
6
|
+
checked: 0,
|
|
7
|
+
detached: 0,
|
|
8
|
+
suspended: 0,
|
|
9
|
+
orphans: 0,
|
|
10
|
+
pendingUpdates: 0,
|
|
11
|
+
mismatches: [],
|
|
12
|
+
errors: [],
|
|
13
|
+
})
|
package/src/index.ts
CHANGED
|
@@ -8,9 +8,12 @@ if (majorReactVersions === undefined || majorReactVersions < 19) {
|
|
|
8
8
|
|
|
9
9
|
export { StyleSheet, UnistylesRuntime } from './specs'
|
|
10
10
|
export { UnistyleDependency } from './specs'
|
|
11
|
+
export type { UnistylesMiniRuntime } from './specs'
|
|
12
|
+
export { ColorScheme, Orientation, StatusBarStyle } from './specs/types'
|
|
11
13
|
export { mq } from './mq'
|
|
12
14
|
export type { UnistylesThemes, UnistylesBreakpoints } from './global'
|
|
13
15
|
export { withUnistyles, useUnistyles, createUnistylesElement } from './core'
|
|
14
|
-
export type { UnistylesVariants, UnistylesValues
|
|
16
|
+
export type { UnistylesVariants, UnistylesValues } from './types'
|
|
17
|
+
export { IOSContentSizeCategory, AndroidContentSizeCategory, WebContentSizeCategory } from './types'
|
|
15
18
|
export { Display, Hide, ScopedTheme } from './components'
|
|
16
19
|
export { useServerUnistyles, hydrateServerUnistyles, getServerUnistyles, resetServerUnistyles } from './server'
|
package/src/mocks.ts
CHANGED
|
@@ -146,6 +146,47 @@ jest.mock('react-native-unistyles', () => {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
return {
|
|
149
|
+
ColorScheme: {
|
|
150
|
+
Light: 'light',
|
|
151
|
+
Dark: 'dark',
|
|
152
|
+
Unspecified: 'unspecified',
|
|
153
|
+
},
|
|
154
|
+
Orientation: {
|
|
155
|
+
Portrait: 'portrait',
|
|
156
|
+
Landscape: 'landscape',
|
|
157
|
+
},
|
|
158
|
+
StatusBarStyle: {
|
|
159
|
+
Default: 'default',
|
|
160
|
+
Light: 'light',
|
|
161
|
+
Dark: 'dark',
|
|
162
|
+
},
|
|
163
|
+
IOSContentSizeCategory: {
|
|
164
|
+
AccessibilityExtraExtraExtraLarge: 'accessibilityExtraExtraExtraLarge',
|
|
165
|
+
AccessibilityExtraExtraLarge: 'accessibilityExtraExtraLarge',
|
|
166
|
+
AccessibilityExtraLarge: 'accessibilityExtraLarge',
|
|
167
|
+
AccessibilityLarge: 'accessibilityLarge',
|
|
168
|
+
AccessibilityMedium: 'accessibilityMedium',
|
|
169
|
+
ExtraExtraExtraLarge: 'xxxLarge',
|
|
170
|
+
ExtraExtraLarge: 'xxLarge',
|
|
171
|
+
ExtraLarge: 'xLarge',
|
|
172
|
+
Large: 'Large',
|
|
173
|
+
Medium: 'Medium',
|
|
174
|
+
Small: 'Small',
|
|
175
|
+
ExtraSmall: 'xSmall',
|
|
176
|
+
Unspecified: 'unspecified',
|
|
177
|
+
},
|
|
178
|
+
AndroidContentSizeCategory: {
|
|
179
|
+
Small: 'Small',
|
|
180
|
+
Default: 'Default',
|
|
181
|
+
Large: 'Large',
|
|
182
|
+
ExtraLarge: 'ExtraLarge',
|
|
183
|
+
Huge: 'Huge',
|
|
184
|
+
ExtraHuge: 'ExtraHuge',
|
|
185
|
+
ExtraExtraHuge: 'ExtraExtraHuge',
|
|
186
|
+
},
|
|
187
|
+
WebContentSizeCategory: {
|
|
188
|
+
Unspecified: 'web-unspecified',
|
|
189
|
+
},
|
|
149
190
|
Hide: () => null,
|
|
150
191
|
Display: () => null,
|
|
151
192
|
ScopedTheme: () => null,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useLayoutEffect } from 'react'
|
|
1
|
+
import { useEffect, useLayoutEffect, useRef } from 'react'
|
|
2
2
|
import { useSharedValue } from 'react-native-reanimated'
|
|
3
3
|
|
|
4
4
|
import type { UseUpdateVariantColorConfig } from './types'
|
|
@@ -12,6 +12,7 @@ export const useUpdateVariantColor = <T extends Record<string, any>>({
|
|
|
12
12
|
}: UseUpdateVariantColorConfig<T>) => {
|
|
13
13
|
const fromValue = useSharedValue<string>(style[colorKey])
|
|
14
14
|
const toValue = useSharedValue<string>(style[colorKey])
|
|
15
|
+
const applied = useRef<{ style: T; colorKey: typeof colorKey }>(undefined)
|
|
15
16
|
|
|
16
17
|
useEffect(() => {
|
|
17
18
|
const dispose = StyleSheet.addChangeListener((changedDependencies) => {
|
|
@@ -31,6 +32,11 @@ export const useUpdateVariantColor = <T extends Record<string, any>>({
|
|
|
31
32
|
}, [style, colorKey])
|
|
32
33
|
|
|
33
34
|
useLayoutEffect(() => {
|
|
35
|
+
if (applied.current?.style === style && applied.current.colorKey === colorKey) {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
applied.current = { style, colorKey }
|
|
34
40
|
fromValue.set(toValue.value)
|
|
35
41
|
toValue.set(style[colorKey])
|
|
36
42
|
}, [style, colorKey])
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { NitroModules } from 'react-native-nitro-modules'
|
|
2
2
|
|
|
3
|
+
import type { VerifyReport } from '../../diagnostics/types'
|
|
3
4
|
import type { UnistylesShadowRegistry as UnistylesShadowRegistrySpec } from './ShadowRegistry.nitro'
|
|
4
5
|
import type { ShadowNode, Unistyle, ViewHandle } from './types'
|
|
5
6
|
|
|
7
|
+
import { StyleSheet } from '../StyleSheet'
|
|
8
|
+
|
|
6
9
|
interface ShadowRegistry extends UnistylesShadowRegistrySpec {
|
|
7
10
|
// Babel API
|
|
8
11
|
add(handle?: ViewHandle, styles?: Array<Unistyle>): void
|
|
@@ -14,10 +17,14 @@ interface ShadowRegistry extends UnistylesShadowRegistrySpec {
|
|
|
14
17
|
flush(): void
|
|
15
18
|
setScopedTheme(themeName?: string): void
|
|
16
19
|
getScopedTheme(): string | undefined
|
|
20
|
+
verify(): VerifyReport
|
|
21
|
+
takeCommittedTags(): Array<number>
|
|
22
|
+
refreshReactNodes(nodes: Array<ShadowNode>): void
|
|
17
23
|
}
|
|
18
24
|
|
|
19
25
|
const HybridShadowRegistry = NitroModules.createHybridObject<ShadowRegistry>('UnistylesShadowRegistry')
|
|
20
26
|
|
|
27
|
+
const HOST_COMPONENT_TAG = 5
|
|
21
28
|
const SUSPENSE_TAG = 13
|
|
22
29
|
const OFFSCREEN_TAG = 22
|
|
23
30
|
|
|
@@ -65,6 +72,123 @@ const findShadowNodeForHandle = (handle: ViewHandle) => {
|
|
|
65
72
|
return node
|
|
66
73
|
}
|
|
67
74
|
|
|
75
|
+
const getNativeTag = (handle: ViewHandle): number | undefined =>
|
|
76
|
+
findFiberForHandle(handle)?.stateNode?.canonical?.nativeTag
|
|
77
|
+
|
|
78
|
+
// by native tag, weak: views unmounted while frozen never unlink, their dead refs are dropped when the map doubles
|
|
79
|
+
const linkedHandles = new Map<number, WeakRef<ViewHandle>>()
|
|
80
|
+
const MIN_SWEEP_SIZE = 256
|
|
81
|
+
let sweepSize = MIN_SWEEP_SIZE
|
|
82
|
+
|
|
83
|
+
const sweepUnmountedHandles = () => {
|
|
84
|
+
linkedHandles.forEach((ref, tag) => {
|
|
85
|
+
if (!ref.deref()) {
|
|
86
|
+
linkedHandles.delete(tag)
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
sweepSize = Math.max(MIN_SWEEP_SIZE, linkedHandles.size * 2)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const trackHandle = (handle: ViewHandle) => {
|
|
94
|
+
const tag = getNativeTag(handle)
|
|
95
|
+
|
|
96
|
+
// views re-link on every render
|
|
97
|
+
if (tag === undefined || linkedHandles.get(tag)?.deref() === handle) {
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
linkedHandles.set(tag, new WeakRef(handle))
|
|
102
|
+
|
|
103
|
+
if (linkedHandles.size >= sweepSize) {
|
|
104
|
+
sweepUnmountedHandles()
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const untrackHandle = (handle: ViewHandle) => {
|
|
109
|
+
const tag = getNativeTag(handle)
|
|
110
|
+
|
|
111
|
+
if (tag !== undefined && linkedHandles.get(tag)?.deref() === handle) {
|
|
112
|
+
linkedHandles.delete(tag)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// React re-attaches an untouched subtree through its root's node and only follows clones made on the JS thread.
|
|
117
|
+
// Once a node was cloned elsewhere (state updates, Reanimated), React would commit a subtree from before a Unistyles
|
|
118
|
+
// update, so after a Unistyles commit the committed nodes and their host ancestors must point at the committed tree
|
|
119
|
+
const refreshReactNodes = () => {
|
|
120
|
+
const tags = HybridShadowRegistry.takeCommittedTags()
|
|
121
|
+
|
|
122
|
+
if (tags.length === 0) {
|
|
123
|
+
return
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const nodes = new Set<ShadowNode>()
|
|
127
|
+
const visited = new Set<any>()
|
|
128
|
+
|
|
129
|
+
for (const tag of tags) {
|
|
130
|
+
const handle = linkedHandles.get(tag)?.deref()
|
|
131
|
+
|
|
132
|
+
if (!handle) {
|
|
133
|
+
continue
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const fiber = findFiberForHandle(handle)
|
|
137
|
+
|
|
138
|
+
// hidden by Suspense or a frozen screen
|
|
139
|
+
if (!fiber || isInsideSuspendedBoundary(fiber)) {
|
|
140
|
+
continue
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
for (let current: any = fiber; current && !visited.has(current); current = current.return) {
|
|
144
|
+
visited.add(current)
|
|
145
|
+
|
|
146
|
+
if (current.alternate) {
|
|
147
|
+
visited.add(current.alternate)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (current.tag !== HOST_COMPONENT_TAG) {
|
|
151
|
+
continue
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
for (const target of [current, current.alternate]) {
|
|
155
|
+
const node = target?.stateNode?.node
|
|
156
|
+
|
|
157
|
+
if (node) {
|
|
158
|
+
nodes.add(node)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (nodes.size > 0) {
|
|
165
|
+
HybridShadowRegistry.refreshReactNodes(Array.from(nodes))
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
StyleSheet.addChangeListener(refreshReactNodes)
|
|
170
|
+
|
|
171
|
+
// runs for every style on every link, so it allocates only for the rare merged style (eg. flattened by Animated)
|
|
172
|
+
const splitMergedUnistyles = (style: any) => {
|
|
173
|
+
let hasUnistyle = false
|
|
174
|
+
|
|
175
|
+
for (const key in style) {
|
|
176
|
+
if (!key.startsWith('unistyles_') || !Object.prototype.hasOwnProperty.call(style, key)) {
|
|
177
|
+
continue
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (hasUnistyle) {
|
|
181
|
+
return Object.keys(style)
|
|
182
|
+
.filter((unistyleKey) => unistyleKey.startsWith('unistyles_'))
|
|
183
|
+
.map((unistyleKey) => ({ [unistyleKey]: style[unistyleKey] }))
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
hasUnistyle = true
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return style
|
|
190
|
+
}
|
|
191
|
+
|
|
68
192
|
HybridShadowRegistry.add = (handle, styles) => {
|
|
69
193
|
// virtualized nodes can be null
|
|
70
194
|
if (!handle || !styles) {
|
|
@@ -78,6 +202,7 @@ HybridShadowRegistry.add = (handle, styles) => {
|
|
|
78
202
|
.filter((style) => style && Object.keys(style).length > 0)
|
|
79
203
|
.flat()
|
|
80
204
|
.filter(Boolean)
|
|
205
|
+
.flatMap(splitMergedUnistyles)
|
|
81
206
|
|
|
82
207
|
if (filteredStyles.length > 0) {
|
|
83
208
|
const node = findShadowNodeForHandle(handle)
|
|
@@ -89,6 +214,7 @@ HybridShadowRegistry.add = (handle, styles) => {
|
|
|
89
214
|
}
|
|
90
215
|
|
|
91
216
|
HybridShadowRegistry.link(node, filteredStyles)
|
|
217
|
+
trackHandle(handle)
|
|
92
218
|
}
|
|
93
219
|
}
|
|
94
220
|
|
|
@@ -106,10 +232,11 @@ HybridShadowRegistry.remove = (handle) => {
|
|
|
106
232
|
HybridShadowRegistry.suspend(maybeNode)
|
|
107
233
|
} else {
|
|
108
234
|
HybridShadowRegistry.unlink(maybeNode)
|
|
235
|
+
untrackHandle(handle)
|
|
109
236
|
}
|
|
110
237
|
}
|
|
111
238
|
}
|
|
112
239
|
|
|
113
|
-
type PrivateMethods = 'add' | 'remove' | 'link' | 'unlink' | 'suspend'
|
|
240
|
+
type PrivateMethods = 'add' | 'remove' | 'link' | 'unlink' | 'suspend' | 'takeCommittedTags' | 'refreshReactNodes'
|
|
114
241
|
|
|
115
242
|
export const UnistylesShadowRegistry = HybridShadowRegistry as Omit<ShadowRegistry, PrivateMethods>
|
|
@@ -34,8 +34,15 @@ export type UnistylesConfig = {
|
|
|
34
34
|
breakpoints?: UnistylesBreakpoints
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
// React Native 0.85 dropped `absoluteFillObject`, where `absoluteFill` is already a plain
|
|
38
|
+
// style object. Older versions still expose both, so the descriptor is read from React Native
|
|
39
|
+
// instead of being duplicated here.
|
|
40
|
+
type AbsoluteFillObject = typeof NativeStyleSheetType extends { absoluteFillObject: infer TStyle }
|
|
41
|
+
? TStyle
|
|
42
|
+
: typeof NativeStyleSheetType.absoluteFill
|
|
43
|
+
|
|
37
44
|
export interface UnistylesStyleSheet extends UnistylesStyleSheetSpec {
|
|
38
|
-
absoluteFillObject:
|
|
45
|
+
absoluteFillObject: AbsoluteFillObject
|
|
39
46
|
absoluteFill: typeof NativeStyleSheetType.absoluteFill
|
|
40
47
|
compose: typeof NativeStyleSheetType.compose
|
|
41
48
|
flatten: typeof NativeStyleSheetType.flatten
|
|
@@ -52,7 +59,8 @@ export interface UnistylesStyleSheet extends UnistylesStyleSheetSpec {
|
|
|
52
59
|
|
|
53
60
|
const HybridUnistylesStyleSheet = NitroModules.createHybridObject<UnistylesStyleSheet>('UnistylesStyleSheet')
|
|
54
61
|
|
|
55
|
-
HybridUnistylesStyleSheet.absoluteFillObject = NativeStyleSheet.
|
|
62
|
+
HybridUnistylesStyleSheet.absoluteFillObject = ((NativeStyleSheet as Record<string, unknown>).absoluteFillObject ??
|
|
63
|
+
NativeStyleSheet.absoluteFill) as AbsoluteFillObject
|
|
56
64
|
HybridUnistylesStyleSheet.absoluteFill = NativeStyleSheet.absoluteFill
|
|
57
65
|
HybridUnistylesStyleSheet.flatten = NativeStyleSheet.flatten
|
|
58
66
|
HybridUnistylesStyleSheet.compose = NativeStyleSheet.compose
|
|
@@ -2,7 +2,12 @@ import { processColor } from 'react-native'
|
|
|
2
2
|
import { NitroModules } from 'react-native-nitro-modules'
|
|
3
3
|
|
|
4
4
|
import type { UnistylesThemes } from '../../global'
|
|
5
|
-
import type {
|
|
5
|
+
import type {
|
|
6
|
+
AndroidContentSizeCategory,
|
|
7
|
+
IOSContentSizeCategory,
|
|
8
|
+
UnistylesTheme,
|
|
9
|
+
WebContentSizeCategory,
|
|
10
|
+
} from '../../types'
|
|
6
11
|
import type { UnistylesNavigationBar } from '../NavigtionBar'
|
|
7
12
|
import type { AppBreakpoint, AppTheme, AppThemeName, Color, ColorScheme, Orientation } from '../types'
|
|
8
13
|
import type { UnistylesMiniRuntime, UnistylesRuntime as UnistylesRuntimeSpec } from './UnistylesRuntime.nitro'
|
|
@@ -13,7 +18,7 @@ import { type UnistylesStatusBar, attachStatusBarJSMethods } from '../StatusBar'
|
|
|
13
18
|
export interface UnistylesRuntimePrivate extends Omit<UnistylesRuntimeSpec, 'setRootViewBackgroundColor'> {
|
|
14
19
|
readonly colorScheme: ColorScheme
|
|
15
20
|
readonly themeName?: AppThemeName
|
|
16
|
-
readonly contentSizeCategory: IOSContentSizeCategory | AndroidContentSizeCategory
|
|
21
|
+
readonly contentSizeCategory: IOSContentSizeCategory | AndroidContentSizeCategory | WebContentSizeCategory
|
|
17
22
|
readonly breakpoint?: AppBreakpoint
|
|
18
23
|
readonly orientation: Orientation
|
|
19
24
|
|
package/src/types/breakpoints.ts
CHANGED
|
@@ -9,9 +9,11 @@ type ExtractTransformArray<T> = T extends object ? { [K in keyof T]: ExtractBrea
|
|
|
9
9
|
type ExtractBreakpoints<T> = T extends object
|
|
10
10
|
? keyof T extends BreakpointsOrMediaQueries
|
|
11
11
|
? T[keyof T]
|
|
12
|
-
: T extends
|
|
13
|
-
? Array<
|
|
14
|
-
|
|
12
|
+
: T extends ReadonlyArray<ToDeepUnistyles<TransformStyles>>
|
|
13
|
+
? T extends Array<infer _U>
|
|
14
|
+
? Array<ExtractTransformArray<T[number]>>
|
|
15
|
+
: ReadonlyArray<ExtractTransformArray<T[number]>>
|
|
16
|
+
: T extends ReadonlyArray<infer _U>
|
|
15
17
|
? T
|
|
16
18
|
: {
|
|
17
19
|
[K in keyof T]: ExtractBreakpoints<T[K]>
|
package/src/types/stylesheet.ts
CHANGED
|
@@ -18,9 +18,9 @@ export type UnistyleImage = Omit<ImageStyle, NestedKeys>
|
|
|
18
18
|
type UnistyleNestedStyles = {
|
|
19
19
|
shadowOffset?: ToDeepUnistyles<ShadowOffset>
|
|
20
20
|
textShadowOffset?: ToDeepUnistyles<ShadowOffset>
|
|
21
|
-
transform?:
|
|
22
|
-
boxShadow?:
|
|
23
|
-
filter?:
|
|
21
|
+
transform?: ReadonlyArray<ToDeepUnistyles<TransformStyles>>
|
|
22
|
+
boxShadow?: ReadonlyArray<ToDeepUnistyles<BoxShadowValue>> | string
|
|
23
|
+
filter?: ReadonlyArray<ToDeepUnistyles<FilterFunction>> | string
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
type VariantsObject = {
|
package/src/web/registry.ts
CHANGED
|
@@ -90,6 +90,9 @@ export class UnistylesRegistry {
|
|
|
90
90
|
stylesCounter.delete(ref)
|
|
91
91
|
|
|
92
92
|
if (stylesCounter.size === 0) {
|
|
93
|
+
// Safe to drop now: connect creates a new Set and the cleanup below only checks the DOM
|
|
94
|
+
this.stylesCounter.delete(hash)
|
|
95
|
+
|
|
93
96
|
// Move this to the end of the event loop so the element is removed from the DOM
|
|
94
97
|
return Promise.resolve().then(() => {
|
|
95
98
|
// Check if element is still in the DOM
|