react-native-unistyles 3.4.0 → 3.5.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.
- 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 +4 -0
- package/cxx/converters/TransformOriginConverter.cpp +106 -0
- package/cxx/core/HostUnistyle.cpp +13 -1
- package/cxx/core/HostUnistyle.h +6 -2
- package/cxx/core/RNStyle.h +1 -1
- 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 +344 -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 +60 -15
- 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/core/passForwardRef.js +15 -3
- package/lib/commonjs/core/passForwardRef.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 +42 -1
- 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/commonjs/web/runtime.js +6 -0
- package/lib/commonjs/web/runtime.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 +59 -14
- 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/core/passForwardRef.js +15 -3
- package/lib/module/core/passForwardRef.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 +42 -1
- 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/module/web/runtime.js +6 -0
- package/lib/module/web/runtime.js.map +1 -1
- package/lib/typescript/src/__tests__/passForwardRef.spec.d.ts +2 -0
- package/lib/typescript/src/__tests__/passForwardRef.spec.d.ts.map +1 -0
- package/lib/typescript/src/__tests__/web-runtime.spec.d.ts +2 -0
- package/lib/typescript/src/__tests__/web-runtime.spec.d.ts.map +1 -0
- 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/passForwardRef.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/lib/typescript/src/web/runtime.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 +51 -15
- package/src/core/createUnistylesTouchableHighlight.tsx +69 -0
- package/src/core/index.ts +2 -0
- package/src/core/passForwardRef.ts +16 -4
- 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 +47 -2
- 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
- package/src/web/runtime.ts +6 -0
|
@@ -1,12 +1,29 @@
|
|
|
1
1
|
import type { TextProps } from 'react-native'
|
|
2
2
|
|
|
3
3
|
import { type ComponentType, createElement, forwardRef } from 'react'
|
|
4
|
+
import * as ReactNative from 'react-native'
|
|
4
5
|
|
|
5
6
|
import { createUnistylesElement } from '../../core'
|
|
6
7
|
|
|
8
|
+
const RN = ReactNative as typeof ReactNative & { unstable_NativeText?: unknown }
|
|
9
|
+
|
|
10
|
+
const resolveRCTText = () => {
|
|
11
|
+
// RN 0.83+ re-exports the host component, which at runtime is the 'RCTText' string itself
|
|
12
|
+
if (typeof RN.unstable_NativeText === 'string') {
|
|
13
|
+
return RN.unstable_NativeText
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// older RN has no public handle on it, but reading Text evaluates the very same module
|
|
17
|
+
if (!RN.Text) {
|
|
18
|
+
throw new Error('Unistyles 🦄: react-native did not expose Text, unable to render NativeText')
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return 'RCTText'
|
|
22
|
+
}
|
|
23
|
+
|
|
7
24
|
// credits to @hirbod
|
|
8
25
|
const LeanText = forwardRef((props, ref) => {
|
|
9
|
-
return createElement(
|
|
26
|
+
return createElement(resolveRCTText(), { ...props, ref })
|
|
10
27
|
}) as ComponentType<TextProps>
|
|
11
28
|
|
|
12
29
|
LeanText.displayName = 'RCTText'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { Text } from './Text'
|
|
1
|
+
export { Text, Text as NativeText } from './Text'
|
|
@@ -1,15 +1,35 @@
|
|
|
1
1
|
import type { ViewProps } from 'react-native'
|
|
2
2
|
|
|
3
3
|
import { type ComponentType, createElement, forwardRef } from 'react'
|
|
4
|
+
import * as ReactNative from 'react-native'
|
|
4
5
|
|
|
5
6
|
import { createUnistylesElement } from '../../core'
|
|
6
7
|
|
|
8
|
+
const RN = ReactNative as typeof ReactNative & { unstable_NativeView?: unknown }
|
|
9
|
+
|
|
10
|
+
const resolveRCTView = () => {
|
|
11
|
+
// RN 0.83+ re-exports the host component, which at runtime is the 'RCTView' string itself
|
|
12
|
+
if (typeof RN.unstable_NativeView === 'string') {
|
|
13
|
+
return RN.unstable_NativeView
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// older RN has no public handle on it, but reading View evaluates the very same module
|
|
17
|
+
if (!RN.View) {
|
|
18
|
+
throw new Error('Unistyles 🦄: react-native did not expose View, unable to render NativeView')
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return 'RCTView'
|
|
22
|
+
}
|
|
23
|
+
|
|
7
24
|
// credits to @hirbod
|
|
8
25
|
const LeanView = forwardRef((props, ref) => {
|
|
9
|
-
return createElement(
|
|
26
|
+
return createElement(resolveRCTView(), { ...props, ref })
|
|
10
27
|
}) as ComponentType<ViewProps>
|
|
11
28
|
|
|
12
29
|
LeanView.displayName = 'RCTView'
|
|
13
30
|
|
|
31
|
+
// named export matches unstable_NativeView from react-native
|
|
32
|
+
export const NativeView = createUnistylesElement(LeanView)
|
|
33
|
+
|
|
14
34
|
// this will match default export from react-native
|
|
15
|
-
export default
|
|
35
|
+
export default NativeView
|
|
@@ -41,9 +41,14 @@ export const Pressable: React.ForwardRefExoticComponent<PressableProps & React.R
|
|
|
41
41
|
isServer()
|
|
42
42
|
? undefined
|
|
43
43
|
: (ref) => {
|
|
44
|
+
if (!ref) {
|
|
45
|
+
// @ts-expect-error hidden from TS
|
|
46
|
+
UnistylesShadowRegistry.remove(storedRef, classNames?.[0].hash)
|
|
47
|
+
}
|
|
48
|
+
|
|
44
49
|
storedRef = ref as unknown as HTMLElement
|
|
45
50
|
// @ts-expect-error hidden from TS
|
|
46
|
-
UnistylesShadowRegistry.add(storedRef, classNames?.hash)
|
|
51
|
+
UnistylesShadowRegistry.add(storedRef, classNames?.[0].hash)
|
|
47
52
|
|
|
48
53
|
if (typeof forwardedRef === 'function') {
|
|
49
54
|
return forwardedRef(ref)
|
|
@@ -61,10 +66,10 @@ export const Pressable: React.ForwardRefExoticComponent<PressableProps & React.R
|
|
|
61
66
|
UnistylesShadowRegistry.setScopedTheme(scopedTheme)
|
|
62
67
|
|
|
63
68
|
// @ts-expect-error hidden from TS
|
|
64
|
-
UnistylesShadowRegistry.remove(storedRef, classNames?.hash)
|
|
69
|
+
UnistylesShadowRegistry.remove(storedRef, classNames?.[0].hash)
|
|
65
70
|
classNames = getClassName(styleResult as UnistylesValues)
|
|
66
71
|
// @ts-expect-error hidden from TS
|
|
67
|
-
UnistylesShadowRegistry.add(storedRef, classNames?.hash)
|
|
72
|
+
UnistylesShadowRegistry.add(storedRef, classNames?.[0].hash)
|
|
68
73
|
|
|
69
74
|
UnistylesShadowRegistry.setScopedTheme(previousScopedTheme)
|
|
70
75
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ActivityIndicator } from 'react-native'
|
|
2
|
+
|
|
3
|
+
import React from 'react'
|
|
4
|
+
|
|
5
|
+
import { isAndroid } from '../common'
|
|
6
|
+
import { UnistylesShadowRegistry } from '../specs'
|
|
7
|
+
import { copyComponentProperties } from '../utils'
|
|
8
|
+
import { passForwardedRef } from './passForwardRef'
|
|
9
|
+
import { maybeWarnAboutMultipleUnistyles } from './warn'
|
|
10
|
+
|
|
11
|
+
const getWrapperHandle = (ref: any) => {
|
|
12
|
+
const spinner = ref?.__internalInstanceHandle
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
__internalInstanceHandle: isAndroid ? spinner?.return?.return : spinner?.return,
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const createUnistylesActivityIndicator = (Component: typeof ActivityIndicator) => {
|
|
20
|
+
const UnistylesActivityIndicator = (props: any) => {
|
|
21
|
+
return (
|
|
22
|
+
<Component
|
|
23
|
+
{...props}
|
|
24
|
+
ref={(ref: unknown) => {
|
|
25
|
+
maybeWarnAboutMultipleUnistyles(props.style, 'ActivityIndicator')
|
|
26
|
+
|
|
27
|
+
const wrapperHandle = getWrapperHandle(ref)
|
|
28
|
+
|
|
29
|
+
return passForwardedRef(
|
|
30
|
+
ref,
|
|
31
|
+
props.ref,
|
|
32
|
+
() => {
|
|
33
|
+
// @ts-ignore this is hidden from TS
|
|
34
|
+
UnistylesShadowRegistry.add(wrapperHandle, props.style)
|
|
35
|
+
},
|
|
36
|
+
() => {
|
|
37
|
+
// @ts-ignore this is hidden from TS
|
|
38
|
+
UnistylesShadowRegistry.remove(wrapperHandle)
|
|
39
|
+
},
|
|
40
|
+
)
|
|
41
|
+
}}
|
|
42
|
+
/>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return copyComponentProperties(Component, UnistylesActivityIndicator)
|
|
47
|
+
}
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
import type { ViewStyle } from 'react-native'
|
|
2
2
|
|
|
3
|
-
import React from 'react'
|
|
3
|
+
import React, { useCallback, useLayoutEffect, useRef } from 'react'
|
|
4
4
|
|
|
5
5
|
import type { UnistylesValues } from '../types'
|
|
6
6
|
|
|
7
7
|
import { copyComponentProperties } from '../utils'
|
|
8
|
+
import * as unistyles from '../web/services'
|
|
8
9
|
import { isServer } from '../web/utils'
|
|
9
|
-
import { createUnistylesRef } from '../web/utils/createUnistylesRef'
|
|
10
10
|
import { getClassName } from './getClassname'
|
|
11
11
|
import { maybeWarnAboutMultipleUnistyles } from './warn'
|
|
12
12
|
|
|
13
|
-
const STYLE_PROPS = [
|
|
13
|
+
const STYLE_PROPS = [
|
|
14
|
+
'contentContainerStyle',
|
|
15
|
+
'columnWrapperStyle',
|
|
16
|
+
'ListHeaderComponentStyle',
|
|
17
|
+
'ListFooterComponentStyle',
|
|
18
|
+
] as const
|
|
14
19
|
|
|
15
20
|
type StyleProp = (typeof STYLE_PROPS)[number] | 'style'
|
|
16
21
|
|
|
@@ -18,28 +23,59 @@ type ComponentProps = {
|
|
|
18
23
|
[K in StyleProp]?: UnistylesValues
|
|
19
24
|
}
|
|
20
25
|
|
|
21
|
-
const buildUnistylesProps = (Component: any, props: ComponentProps
|
|
26
|
+
const buildUnistylesProps = (Component: any, props: ComponentProps) => {
|
|
22
27
|
const componentStyleProps = ['style' as const, ...STYLE_PROPS.filter((styleProp) => styleProp in props)]
|
|
23
|
-
const classNames = Object.fromEntries(
|
|
24
|
-
componentStyleProps.map((styleProp) => [styleProp, getClassName(props[styleProp])]),
|
|
25
|
-
)
|
|
26
|
-
const refs = componentStyleProps.map((styleProp) => {
|
|
27
|
-
return createUnistylesRef(classNames[styleProp], styleProp === 'style' ? forwardedRef : undefined)
|
|
28
|
-
})
|
|
29
28
|
|
|
30
29
|
componentStyleProps.forEach((styleProp) => {
|
|
31
30
|
maybeWarnAboutMultipleUnistyles(props[styleProp] as ViewStyle, Component.displayName)
|
|
32
31
|
})
|
|
33
32
|
|
|
34
|
-
return
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
return Object.fromEntries(componentStyleProps.map((styleProp) => [styleProp, getClassName(props[styleProp])]))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const assignRef = (ref: React.Ref<unknown> | undefined, value: unknown) => {
|
|
37
|
+
if (typeof ref === 'function') {
|
|
38
|
+
ref(value)
|
|
39
|
+
} else if (ref) {
|
|
40
|
+
ref.current = value
|
|
37
41
|
}
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
export const createUnistylesElement = (Component: any) => {
|
|
41
|
-
const UnistylesComponent = (props: any) => {
|
|
42
|
-
|
|
45
|
+
const UnistylesComponent = ({ ref, ...props }: any) => {
|
|
46
|
+
const classNames = buildUnistylesProps(Component, props)
|
|
47
|
+
const hashes = Object.values(classNames).map((className) => className?.[0].hash)
|
|
48
|
+
const stored = useRef({ node: null as unknown, hashes, ref })
|
|
49
|
+
// Stable for the component lifetime, as some components (e.g. ScrollView) call only the latest ref on unmount
|
|
50
|
+
const unistylesRef = useCallback((node: unknown) => {
|
|
51
|
+
const { shadowRegistry } = unistyles.services
|
|
52
|
+
|
|
53
|
+
stored.current.hashes.forEach((hash) =>
|
|
54
|
+
node ? shadowRegistry.add(node, hash) : shadowRegistry.remove(stored.current.node, hash),
|
|
55
|
+
)
|
|
56
|
+
stored.current.node = node
|
|
57
|
+
assignRef(stored.current.ref, node)
|
|
58
|
+
}, [])
|
|
59
|
+
|
|
60
|
+
// React won't call a stable ref again, so apply style and ref changes after commit
|
|
61
|
+
useLayoutEffect(() => {
|
|
62
|
+
const { shadowRegistry } = unistyles.services
|
|
63
|
+
const { node, hashes: previousHashes, ref: previousRef } = stored.current
|
|
64
|
+
|
|
65
|
+
if (previousHashes.join() !== hashes.join()) {
|
|
66
|
+
previousHashes.forEach((hash) => shadowRegistry.remove(node, hash))
|
|
67
|
+
hashes.forEach((hash) => shadowRegistry.add(node, hash))
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (previousRef !== ref) {
|
|
71
|
+
assignRef(previousRef, null)
|
|
72
|
+
assignRef(ref, node)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
stored.current = { node, hashes, ref }
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
return <Component {...props} {...classNames} ref={isServer() ? undefined : unistylesRef} />
|
|
43
79
|
}
|
|
44
80
|
|
|
45
81
|
return copyComponentProperties(Component, UnistylesComponent)
|
|
@@ -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'
|
|
@@ -6,7 +6,7 @@ export const passForwardedRef = <T>(
|
|
|
6
6
|
onMount?: () => void,
|
|
7
7
|
onUnmount?: () => void,
|
|
8
8
|
) => {
|
|
9
|
-
const passForwardedRef = () => {
|
|
9
|
+
const passForwardedRef = (): unknown => {
|
|
10
10
|
if (typeof forwardedRef === 'function') {
|
|
11
11
|
return forwardedRef(ref)
|
|
12
12
|
}
|
|
@@ -15,14 +15,26 @@ export const passForwardedRef = <T>(
|
|
|
15
15
|
forwardedRef.current = ref
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
return
|
|
18
|
+
return undefined
|
|
19
19
|
}
|
|
20
20
|
const forwardedRefReturnFn = passForwardedRef()
|
|
21
21
|
|
|
22
22
|
onMount?.()
|
|
23
23
|
|
|
24
24
|
return () => {
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
try {
|
|
26
|
+
// React 19 allows a callback ref to return a cleanup function, but returning
|
|
27
|
+
// any other value is still valid, so it can't be called unconditionally.
|
|
28
|
+
// Without a cleanup function React detaches the ref with null, so do we.
|
|
29
|
+
if (typeof forwardedRefReturnFn === 'function') {
|
|
30
|
+
forwardedRefReturnFn()
|
|
31
|
+
} else if (typeof forwardedRef === 'function') {
|
|
32
|
+
forwardedRef(null)
|
|
33
|
+
} else if (forwardedRef) {
|
|
34
|
+
forwardedRef.current = null
|
|
35
|
+
}
|
|
36
|
+
} finally {
|
|
37
|
+
onUnmount?.()
|
|
38
|
+
}
|
|
27
39
|
}
|
|
28
40
|
}
|
|
@@ -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
|
@@ -11,6 +11,10 @@ type Registry = {
|
|
|
11
11
|
breakpoints: UnistylesBreakpoints
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
type GlobalWithRegistry = typeof globalThis & {
|
|
15
|
+
__UNISTYLES_MOCK_REGISTRY__?: Registry
|
|
16
|
+
}
|
|
17
|
+
|
|
14
18
|
jest.mock('react-native-nitro-modules', () => ({
|
|
15
19
|
NitroModules: {
|
|
16
20
|
createHybridObject: () => ({
|
|
@@ -26,10 +30,10 @@ jest.mock('react-native-nitro-modules', () => ({
|
|
|
26
30
|
|
|
27
31
|
jest.mock('react-native-unistyles', () => {
|
|
28
32
|
const React = require('react')
|
|
29
|
-
const _REGISTRY
|
|
33
|
+
const _REGISTRY = ((globalThis as GlobalWithRegistry).__UNISTYLES_MOCK_REGISTRY__ ??= {
|
|
30
34
|
themes: {},
|
|
31
35
|
breakpoints: {},
|
|
32
|
-
}
|
|
36
|
+
})
|
|
33
37
|
const miniRuntime = {
|
|
34
38
|
themeName: undefined,
|
|
35
39
|
breakpoint: undefined,
|
|
@@ -146,6 +150,47 @@ jest.mock('react-native-unistyles', () => {
|
|
|
146
150
|
}
|
|
147
151
|
|
|
148
152
|
return {
|
|
153
|
+
ColorScheme: {
|
|
154
|
+
Light: 'light',
|
|
155
|
+
Dark: 'dark',
|
|
156
|
+
Unspecified: 'unspecified',
|
|
157
|
+
},
|
|
158
|
+
Orientation: {
|
|
159
|
+
Portrait: 'portrait',
|
|
160
|
+
Landscape: 'landscape',
|
|
161
|
+
},
|
|
162
|
+
StatusBarStyle: {
|
|
163
|
+
Default: 'default',
|
|
164
|
+
Light: 'light',
|
|
165
|
+
Dark: 'dark',
|
|
166
|
+
},
|
|
167
|
+
IOSContentSizeCategory: {
|
|
168
|
+
AccessibilityExtraExtraExtraLarge: 'accessibilityExtraExtraExtraLarge',
|
|
169
|
+
AccessibilityExtraExtraLarge: 'accessibilityExtraExtraLarge',
|
|
170
|
+
AccessibilityExtraLarge: 'accessibilityExtraLarge',
|
|
171
|
+
AccessibilityLarge: 'accessibilityLarge',
|
|
172
|
+
AccessibilityMedium: 'accessibilityMedium',
|
|
173
|
+
ExtraExtraExtraLarge: 'xxxLarge',
|
|
174
|
+
ExtraExtraLarge: 'xxLarge',
|
|
175
|
+
ExtraLarge: 'xLarge',
|
|
176
|
+
Large: 'Large',
|
|
177
|
+
Medium: 'Medium',
|
|
178
|
+
Small: 'Small',
|
|
179
|
+
ExtraSmall: 'xSmall',
|
|
180
|
+
Unspecified: 'unspecified',
|
|
181
|
+
},
|
|
182
|
+
AndroidContentSizeCategory: {
|
|
183
|
+
Small: 'Small',
|
|
184
|
+
Default: 'Default',
|
|
185
|
+
Large: 'Large',
|
|
186
|
+
ExtraLarge: 'ExtraLarge',
|
|
187
|
+
Huge: 'Huge',
|
|
188
|
+
ExtraHuge: 'ExtraHuge',
|
|
189
|
+
ExtraExtraHuge: 'ExtraExtraHuge',
|
|
190
|
+
},
|
|
191
|
+
WebContentSizeCategory: {
|
|
192
|
+
Unspecified: 'web-unspecified',
|
|
193
|
+
},
|
|
149
194
|
Hide: () => null,
|
|
150
195
|
Display: () => null,
|
|
151
196
|
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])
|