react-native-unistyles 3.0.0-alpha.34 → 3.0.0-alpha.36
Sign up to get free protection for your applications and to get access to all the features.
- package/android/CMakeLists.txt +31 -36
- package/android/build.gradle +2 -1
- package/android/src/main/cxx/NativeUnistylesModule.cpp +71 -0
- package/android/src/main/cxx/NativeUnistylesModule.h +42 -0
- package/android/src/main/cxx/cpp-adapter.cpp +8 -86
- package/android/src/main/java/com/unistyles/NativePlatform.kt +184 -0
- package/android/src/main/java/com/unistyles/UnistylesModule+insets.kt +8 -0
- package/android/src/main/java/com/unistyles/UnistylesModule.kt +47 -0
- package/android/src/main/java/com/unistyles/UnistylesPackage.kt +16 -14
- package/cxx/NativePlatform.h +11 -0
- package/cxx/common/Helpers.h +1 -1
- package/cxx/core/Unistyle.h +1 -1
- package/cxx/core/UnistylesRegistry.h +1 -1
- package/cxx/hybridObjects/HybridNavigationBar.h +3 -3
- package/cxx/hybridObjects/HybridStatusBar.h +3 -3
- package/cxx/hybridObjects/HybridUnistylesRuntime.cpp +4 -4
- package/cxx/hybridObjects/HybridUnistylesRuntime.h +2 -2
- package/lib/commonjs/components/useMedia.js.map +1 -1
- package/lib/commonjs/components/useMedia.web.js +43 -0
- package/lib/commonjs/components/useMedia.web.js.map +1 -0
- package/lib/commonjs/core/createUnistylesComponent.js +57 -4
- package/lib/commonjs/core/createUnistylesComponent.js.map +1 -1
- package/lib/commonjs/core/createUnistylesComponent.native.js +6 -5
- package/lib/commonjs/core/createUnistylesComponent.native.js.map +1 -1
- package/lib/commonjs/specs/ShadowRegistry/index.js +5 -0
- package/lib/commonjs/specs/ShadowRegistry/index.js.map +1 -1
- package/lib/commonjs/web/convert/index.js +16 -11
- package/lib/commonjs/web/convert/index.js.map +1 -1
- package/lib/commonjs/web/convert/object/boxShadow.js +58 -0
- package/lib/commonjs/web/convert/object/boxShadow.js.map +1 -0
- package/lib/commonjs/web/convert/object/filter.js +42 -0
- package/lib/commonjs/web/convert/object/filter.js.map +1 -0
- package/lib/commonjs/web/convert/object/index.js +39 -0
- package/lib/commonjs/web/convert/object/index.js.map +1 -0
- package/lib/commonjs/web/convert/object/objectStyle.js +55 -0
- package/lib/commonjs/web/convert/object/objectStyle.js.map +1 -0
- package/lib/commonjs/web/convert/object/transform.js +27 -0
- package/lib/commonjs/web/convert/object/transform.js.map +1 -0
- package/lib/commonjs/web/convert/{boxShadow.js → shadow/boxShadow.js} +9 -24
- package/lib/commonjs/web/convert/shadow/boxShadow.js.map +1 -0
- package/lib/commonjs/web/convert/shadow/getShadowBreakpoints.js +38 -0
- package/lib/commonjs/web/convert/shadow/getShadowBreakpoints.js.map +1 -0
- package/lib/commonjs/web/convert/shadow/index.js +28 -0
- package/lib/commonjs/web/convert/shadow/index.js.map +1 -0
- package/lib/commonjs/web/convert/{textShadow.js → shadow/textShadow.js} +9 -23
- package/lib/commonjs/web/convert/shadow/textShadow.js.map +1 -0
- package/lib/commonjs/web/convert/utils.js +7 -3
- package/lib/commonjs/web/convert/utils.js.map +1 -1
- package/lib/commonjs/web/listener.js +10 -0
- package/lib/commonjs/web/listener.js.map +1 -1
- package/lib/commonjs/web/registry.js +13 -26
- package/lib/commonjs/web/registry.js.map +1 -1
- package/lib/commonjs/web/runtime.js +3 -0
- package/lib/commonjs/web/runtime.js.map +1 -1
- package/lib/commonjs/web/shadowRegistry.js +79 -39
- package/lib/commonjs/web/shadowRegistry.js.map +1 -1
- package/lib/commonjs/web/utils/common.js +3 -33
- package/lib/commonjs/web/utils/common.js.map +1 -1
- package/lib/commonjs/web/utils/unistyle.js +4 -1
- package/lib/commonjs/web/utils/unistyle.js.map +1 -1
- package/lib/module/components/useMedia.js.map +1 -1
- package/lib/module/components/useMedia.web.js +38 -0
- package/lib/module/components/useMedia.web.js.map +1 -0
- package/lib/module/core/createUnistylesComponent.js +55 -3
- package/lib/module/core/createUnistylesComponent.js.map +1 -1
- package/lib/module/core/createUnistylesComponent.native.js +6 -5
- package/lib/module/core/createUnistylesComponent.native.js.map +1 -1
- package/lib/module/specs/ShadowRegistry/index.js +5 -0
- package/lib/module/specs/ShadowRegistry/index.js.map +1 -1
- package/lib/module/web/convert/index.js +14 -9
- package/lib/module/web/convert/index.js.map +1 -1
- package/lib/module/web/convert/object/boxShadow.js +53 -0
- package/lib/module/web/convert/object/boxShadow.js.map +1 -0
- package/lib/module/web/convert/object/filter.js +37 -0
- package/lib/module/web/convert/object/filter.js.map +1 -0
- package/lib/module/web/convert/object/index.js +6 -0
- package/lib/module/web/convert/object/index.js.map +1 -0
- package/lib/module/web/convert/object/objectStyle.js +50 -0
- package/lib/module/web/convert/object/objectStyle.js.map +1 -0
- package/lib/module/web/convert/object/transform.js +22 -0
- package/lib/module/web/convert/object/transform.js.map +1 -0
- package/lib/module/web/convert/{boxShadow.js → shadow/boxShadow.js} +9 -24
- package/lib/module/web/convert/shadow/boxShadow.js.map +1 -0
- package/lib/module/web/convert/shadow/getShadowBreakpoints.js +33 -0
- package/lib/module/web/convert/shadow/getShadowBreakpoints.js.map +1 -0
- package/lib/module/web/convert/shadow/index.js +5 -0
- package/lib/module/web/convert/shadow/index.js.map +1 -0
- package/lib/module/web/convert/{textShadow.js → shadow/textShadow.js} +9 -23
- package/lib/module/web/convert/shadow/textShadow.js.map +1 -0
- package/lib/module/web/convert/utils.js +4 -2
- package/lib/module/web/convert/utils.js.map +1 -1
- package/lib/module/web/listener.js +10 -0
- package/lib/module/web/listener.js.map +1 -1
- package/lib/module/web/registry.js +14 -27
- package/lib/module/web/registry.js.map +1 -1
- package/lib/module/web/runtime.js +3 -0
- package/lib/module/web/runtime.js.map +1 -1
- package/lib/module/web/shadowRegistry.js +80 -40
- package/lib/module/web/shadowRegistry.js.map +1 -1
- package/lib/module/web/utils/common.js +1 -31
- package/lib/module/web/utils/common.js.map +1 -1
- package/lib/module/web/utils/unistyle.js +4 -1
- package/lib/module/web/utils/unistyle.js.map +1 -1
- package/lib/typescript/src/components/useMedia.web.d.ts +6 -0
- package/lib/typescript/src/components/useMedia.web.d.ts.map +1 -0
- package/lib/typescript/src/core/createUnistylesComponent.d.ts +4 -3
- package/lib/typescript/src/core/createUnistylesComponent.d.ts.map +1 -1
- package/lib/typescript/src/core/createUnistylesComponent.native.d.ts +4 -3
- package/lib/typescript/src/core/createUnistylesComponent.native.d.ts.map +1 -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/types/common.d.ts +1 -0
- package/lib/typescript/src/types/common.d.ts.map +1 -1
- package/lib/typescript/src/web/convert/index.d.ts.map +1 -1
- package/lib/typescript/src/web/convert/object/boxShadow.d.ts +9 -0
- package/lib/typescript/src/web/convert/object/boxShadow.d.ts.map +1 -0
- package/lib/typescript/src/web/convert/object/filter.d.ts +3 -0
- package/lib/typescript/src/web/convert/object/filter.d.ts.map +1 -0
- package/lib/typescript/src/web/convert/object/index.d.ts +4 -0
- package/lib/typescript/src/web/convert/object/index.d.ts.map +1 -0
- package/lib/typescript/src/web/convert/object/objectStyle.d.ts +5 -0
- package/lib/typescript/src/web/convert/object/objectStyle.d.ts.map +1 -0
- package/lib/typescript/src/web/convert/object/transform.d.ts +3 -0
- package/lib/typescript/src/web/convert/object/transform.d.ts.map +1 -0
- package/lib/typescript/src/web/convert/shadow/boxShadow.d.ts.map +1 -0
- package/lib/typescript/src/web/convert/shadow/getShadowBreakpoints.d.ts +2 -0
- package/lib/typescript/src/web/convert/shadow/getShadowBreakpoints.d.ts.map +1 -0
- package/lib/typescript/src/web/convert/shadow/index.d.ts +3 -0
- package/lib/typescript/src/web/convert/shadow/index.d.ts.map +1 -0
- package/lib/typescript/src/web/convert/shadow/textShadow.d.ts.map +1 -0
- package/lib/typescript/src/web/convert/types.d.ts +7 -1
- package/lib/typescript/src/web/convert/types.d.ts.map +1 -1
- package/lib/typescript/src/web/convert/utils.d.ts +8 -4
- package/lib/typescript/src/web/convert/utils.d.ts.map +1 -1
- package/lib/typescript/src/web/create.d.ts +8 -8
- package/lib/typescript/src/web/index.d.ts +8 -8
- package/lib/typescript/src/web/listener.d.ts +2 -0
- package/lib/typescript/src/web/listener.d.ts.map +1 -1
- package/lib/typescript/src/web/registry.d.ts +5 -9
- package/lib/typescript/src/web/registry.d.ts.map +1 -1
- package/lib/typescript/src/web/runtime.d.ts +1 -0
- package/lib/typescript/src/web/runtime.d.ts.map +1 -1
- package/lib/typescript/src/web/shadowRegistry.d.ts +4 -1
- package/lib/typescript/src/web/shadowRegistry.d.ts.map +1 -1
- package/lib/typescript/src/web/utils/common.d.ts +1 -6
- package/lib/typescript/src/web/utils/common.d.ts.map +1 -1
- package/lib/typescript/src/web/utils/unistyle.d.ts.map +1 -1
- package/nitrogen/generated/android/c++/JHybridNativePlatformSpec.hpp +6 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/unistyles/Dimensions.kt +1 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/unistyles/Func_void.kt +1 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/unistyles/Func_void_std__vector_UnistyleDependency_.kt +1 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/unistyles/Insets.kt +1 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/unistyles/UnistylesNativeMiniRuntime.kt +1 -0
- package/nitrogen/generated/android/unistyles+autolinking.gradle +2 -0
- package/nitrogen/generated/ios/Unistyles+autolinking.rb +1 -1
- package/package.json +3 -3
- package/src/components/useMedia.ts +1 -1
- package/src/components/useMedia.web.ts +47 -0
- package/src/core/createUnistylesComponent.native.tsx +12 -10
- package/src/core/createUnistylesComponent.tsx +72 -6
- package/src/specs/ShadowRegistry/index.ts +5 -0
- package/src/specs/ShadowRegistry/types.ts +4 -1
- package/src/types/common.ts +1 -0
- package/src/web/convert/index.ts +16 -9
- package/src/web/convert/object/boxShadow.ts +54 -0
- package/src/web/convert/object/filter.ts +39 -0
- package/src/web/convert/object/index.ts +3 -0
- package/src/web/convert/object/objectStyle.ts +68 -0
- package/src/web/convert/object/transform.ts +24 -0
- package/src/web/convert/{boxShadow.ts → shadow/boxShadow.ts} +9 -30
- package/src/web/convert/shadow/getShadowBreakpoints.ts +34 -0
- package/src/web/convert/shadow/index.ts +2 -0
- package/src/web/convert/{textShadow.ts → shadow/textShadow.ts} +9 -29
- package/src/web/convert/types.ts +8 -1
- package/src/web/convert/utils.ts +11 -5
- package/src/web/listener.ts +10 -0
- package/src/web/registry.ts +10 -31
- package/src/web/runtime.ts +4 -0
- package/src/web/shadowRegistry.ts +85 -46
- package/src/web/utils/common.ts +1 -37
- package/src/web/utils/unistyle.ts +5 -1
- package/android/src/main/cxx/helpers.cpp +0 -105
- package/android/src/main/cxx/helpers.h +0 -16
- package/android/src/main/cxx/platform.cpp +0 -170
- package/android/src/main/cxx/platform.h +0 -20
- package/lib/commonjs/web/convert/boxShadow.js.map +0 -1
- package/lib/commonjs/web/convert/shadow.js +0 -68
- package/lib/commonjs/web/convert/shadow.js.map +0 -1
- package/lib/commonjs/web/convert/textShadow.js.map +0 -1
- package/lib/commonjs/web/convert/transform.js +0 -72
- package/lib/commonjs/web/convert/transform.js.map +0 -1
- package/lib/module/web/convert/boxShadow.js.map +0 -1
- package/lib/module/web/convert/shadow.js +0 -63
- package/lib/module/web/convert/shadow.js.map +0 -1
- package/lib/module/web/convert/textShadow.js.map +0 -1
- package/lib/module/web/convert/transform.js +0 -67
- package/lib/module/web/convert/transform.js.map +0 -1
- package/lib/typescript/src/web/convert/boxShadow.d.ts.map +0 -1
- package/lib/typescript/src/web/convert/shadow.d.ts +0 -2
- package/lib/typescript/src/web/convert/shadow.d.ts.map +0 -1
- package/lib/typescript/src/web/convert/textShadow.d.ts.map +0 -1
- package/lib/typescript/src/web/convert/transform.d.ts +0 -4
- package/lib/typescript/src/web/convert/transform.d.ts.map +0 -1
- package/src/web/convert/shadow.ts +0 -68
- package/src/web/convert/transform.ts +0 -88
- /package/lib/typescript/src/web/convert/{boxShadow.d.ts → shadow/boxShadow.d.ts} +0 -0
- /package/lib/typescript/src/web/convert/{textShadow.d.ts → shadow/textShadow.d.ts} +0 -0
@@ -31,6 +31,12 @@ namespace margelo::nitro::unistyles {
|
|
31
31
|
HybridObject(HybridNativePlatformSpec::TAG),
|
32
32
|
_javaPart(jni::make_global(jThis)) {}
|
33
33
|
|
34
|
+
public:
|
35
|
+
virtual ~JHybridNativePlatformSpec() {
|
36
|
+
// Hermes GC can destroy JS objects on a non-JNI Thread.
|
37
|
+
jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); });
|
38
|
+
}
|
39
|
+
|
34
40
|
public:
|
35
41
|
size_t getExternalMemorySize() noexcept override;
|
36
42
|
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "react-native-unistyles",
|
3
|
-
"version": "3.0.0-alpha.
|
3
|
+
"version": "3.0.0-alpha.36",
|
4
4
|
"description": "Level up your React Native StyleSheet",
|
5
5
|
"scripts": {
|
6
6
|
"test": "jest",
|
@@ -74,11 +74,11 @@
|
|
74
74
|
"husky": "9.1.6",
|
75
75
|
"jest": "29.7.0",
|
76
76
|
"metro-react-native-babel-preset": "0.77.0",
|
77
|
-
"nitro-codegen": "0.
|
77
|
+
"nitro-codegen": "0.15.0",
|
78
78
|
"react": "18.3.1",
|
79
79
|
"react-native": "0.76.0",
|
80
80
|
"react-native-builder-bob": "0.30.2",
|
81
|
-
"react-native-nitro-modules": "0.
|
81
|
+
"react-native-nitro-modules": "0.15.0",
|
82
82
|
"react-test-renderer": "18.3.1",
|
83
83
|
"release-it": "17.10.0",
|
84
84
|
"typescript": "5.6.3"
|
@@ -12,7 +12,7 @@ export const useMedia = (config: { mq: symbol }) => {
|
|
12
12
|
return false
|
13
13
|
}
|
14
14
|
|
15
|
-
const parsedMq =
|
15
|
+
const parsedMq = parseMq(maybeMq)
|
16
16
|
|
17
17
|
if (!isValidMq(parsedMq)) {
|
18
18
|
console.error(`🦄 Unistyles: Received invalid mq where min is greater than max: ${maybeMq}`)
|
@@ -0,0 +1,47 @@
|
|
1
|
+
import { useEffect, useRef, useState } from 'react'
|
2
|
+
import { isUnistylesMq, isValidMq, parseMq } from '../mq'
|
3
|
+
|
4
|
+
export const useMedia = (config: { mq: symbol }) => {
|
5
|
+
const disposeRef = useRef(() => {})
|
6
|
+
const [isVisible, setIsVisible] = useState(() => {
|
7
|
+
const maybeMq = config.mq as unknown as string
|
8
|
+
|
9
|
+
if (!isUnistylesMq(maybeMq)) {
|
10
|
+
console.error(`🦄 Unistyles: Received invalid mq: ${maybeMq}`)
|
11
|
+
|
12
|
+
return false
|
13
|
+
}
|
14
|
+
|
15
|
+
const parsedMq = parseMq(maybeMq)
|
16
|
+
|
17
|
+
if (!isValidMq(parsedMq)) {
|
18
|
+
console.error(`🦄 Unistyles: Received invalid mq where min is greater than max: ${maybeMq}`)
|
19
|
+
|
20
|
+
return false
|
21
|
+
}
|
22
|
+
|
23
|
+
const { minWidth, maxWidth, minHeight, maxHeight } = parsedMq
|
24
|
+
|
25
|
+
const mediaQuery = [
|
26
|
+
minWidth !== undefined ? `(min-width: ${minWidth}px)` : undefined,
|
27
|
+
maxWidth !== undefined ? `(max-width: ${maxWidth}px)` : undefined,
|
28
|
+
minHeight !== undefined ? `(min-height: ${minHeight}px)` : undefined,
|
29
|
+
maxHeight !== undefined ? `(max-height: ${maxHeight}px)` : undefined
|
30
|
+
].filter(Boolean).join(' and ')
|
31
|
+
|
32
|
+
const media = window.matchMedia(mediaQuery)
|
33
|
+
const handler = (event: MediaQueryListEvent) => setIsVisible(event.matches)
|
34
|
+
|
35
|
+
media.addEventListener('change', handler)
|
36
|
+
disposeRef.current = () => media.removeEventListener('change', handler)
|
37
|
+
|
38
|
+
return media.matches
|
39
|
+
})
|
40
|
+
|
41
|
+
// Unmount
|
42
|
+
useEffect(() => () => disposeRef.current(), [])
|
43
|
+
|
44
|
+
return {
|
45
|
+
isVisible
|
46
|
+
}
|
47
|
+
}
|
@@ -1,13 +1,13 @@
|
|
1
|
-
import React, { type
|
1
|
+
import React, { type ComponentType, useEffect, useRef, useState } from 'react'
|
2
2
|
import type { UnistylesTheme } from '../types'
|
3
3
|
import { StyleSheet, UnistyleDependency, UnistylesRuntime, type UnistylesStyleSheet } from '../specs'
|
4
|
-
|
5
|
-
type Mappings<T extends ComponentType<any>> = (theme: UnistylesTheme) => Partial<Omit<ComponentProps<T>, typeof SUPPORTED_STYLE_PROPS[number]>>
|
4
|
+
import type { PartialBy } from '../types/common'
|
6
5
|
|
7
6
|
const SUPPORTED_STYLE_PROPS = ['style', 'contentContainerStyle'] as const
|
7
|
+
type SupportedStyleProps = typeof SUPPORTED_STYLE_PROPS[number]
|
8
8
|
|
9
|
-
export const createUnistylesComponent
|
10
|
-
return (props:
|
9
|
+
export const createUnistylesComponent =<TProps extends Record<string, any>, TMappings extends Partial<Omit<TProps, SupportedStyleProps>>>(Component: ComponentType<TProps>, mappings?: (theme: UnistylesTheme) => TMappings) => {
|
10
|
+
return (props: PartialBy<TProps, keyof TMappings | SupportedStyleProps>) => {
|
11
11
|
const [theme, setTheme] = useState<UnistylesTheme>(UnistylesRuntime.getTheme())
|
12
12
|
const [, setRt] = useState(0)
|
13
13
|
const stylesRef = useRef<Record<string, any>>({})
|
@@ -20,6 +20,7 @@ export const createUnistylesComponent = <T extends ComponentType<any>>(Component
|
|
20
20
|
console.error(`🦄 Unistyles: createUnistylesComponent requires ${propName} to be an object. Please check props for component: ${Component.displayName}`)
|
21
21
|
}
|
22
22
|
|
23
|
+
// @ts-expect-error - this is hidden from TS
|
23
24
|
if (props[propName].__unistyles_name && !props[propName].__proto__?.getStyle) {
|
24
25
|
console.error(`🦄 Unistyles: createUnistylesComponent received style that is not bound. You likely used the spread operator on a Unistyle style. Please check props for component: ${Component.displayName}`)
|
25
26
|
}
|
@@ -34,7 +35,7 @@ export const createUnistylesComponent = <T extends ComponentType<any>>(Component
|
|
34
35
|
|
35
36
|
useEffect(() => {
|
36
37
|
const removeChangeListener = (StyleSheet as UnistylesStyleSheet).addChangeListener(dependencies => {
|
37
|
-
const componentDependencies = (props.style?.__proto__.uni__dependencies || mappings(theme).style?.__proto__.uni__dependencies) as Array<UnistyleDependency>
|
38
|
+
const componentDependencies = (props.style?.__proto__.uni__dependencies || mappings?.(theme).style?.__proto__.uni__dependencies) as Array<UnistyleDependency>
|
38
39
|
|
39
40
|
if (dependencies.includes(UnistyleDependency.Theme) && (!componentDependencies ||componentDependencies.includes(UnistyleDependency.Theme))) {
|
40
41
|
setTheme(UnistylesRuntime.getTheme())
|
@@ -44,6 +45,7 @@ export const createUnistylesComponent = <T extends ComponentType<any>>(Component
|
|
44
45
|
if (props?.[propName]) {
|
45
46
|
stylesRef.current = {
|
46
47
|
...stylesRef.current,
|
48
|
+
// @ts-expect-error - this is hidden from TS
|
47
49
|
[propName]: props[propName].__proto__?.getStyle() || props[propName]
|
48
50
|
}
|
49
51
|
}
|
@@ -62,16 +64,16 @@ export const createUnistylesComponent = <T extends ComponentType<any>>(Component
|
|
62
64
|
}
|
63
65
|
}, [])
|
64
66
|
|
65
|
-
const mergedProps =
|
67
|
+
const mergedProps = mappings?.(theme) as Record<string, any> ?? {}
|
66
68
|
|
67
69
|
Object.keys(props).forEach(key => {
|
68
70
|
if (key in mergedProps) {
|
69
|
-
mergedProps[key] = Object.assign(props[key], mergedProps[key])
|
71
|
+
mergedProps[key] = Object.assign(props[key as keyof typeof props], mergedProps[key])
|
70
72
|
|
71
73
|
return
|
72
74
|
}
|
73
75
|
|
74
|
-
mergedProps[key] = props[key]
|
76
|
+
mergedProps[key] = props[key as keyof typeof props]
|
75
77
|
})
|
76
78
|
|
77
79
|
// override with Unistyles styles
|
@@ -83,6 +85,6 @@ export const createUnistylesComponent = <T extends ComponentType<any>>(Component
|
|
83
85
|
|
84
86
|
isForcedRef.current = false
|
85
87
|
|
86
|
-
return <Component {...mergedProps} />
|
88
|
+
return <Component {...mergedProps as TProps} />
|
87
89
|
}
|
88
90
|
}
|
@@ -1,12 +1,78 @@
|
|
1
|
-
import React, {
|
1
|
+
import React, { useEffect, useState, type ComponentType } from 'react'
|
2
2
|
import type { UnistylesTheme } from '../types'
|
3
|
-
|
4
|
-
|
3
|
+
import { UnistylesRuntime } from '../specs'
|
4
|
+
import { UnistyleDependency } from '../specs/NativePlatform'
|
5
|
+
import type { PartialBy } from '../types/common'
|
6
|
+
import { UnistylesListener } from '../web/listener'
|
7
|
+
import { UnistylesShadowRegistry } from '../web'
|
8
|
+
import { equal } from '../web/utils'
|
5
9
|
|
6
10
|
const SUPPORTED_STYLE_PROPS = ['style', 'contentContainerStyle'] as const
|
11
|
+
const ALL_DEPENDENCIES = Object.values(UnistyleDependency).filter((dependency): dependency is UnistyleDependency => typeof dependency === 'number')
|
12
|
+
|
13
|
+
type SupportedStyleProps = typeof SUPPORTED_STYLE_PROPS[number]
|
14
|
+
|
15
|
+
const useShadowRegistry = (style?: Record<string, any>) => {
|
16
|
+
const [classNames, setClassNames] = useState<Array<string>>([])
|
17
|
+
const [ref] = useState(document.createElement('div'))
|
18
|
+
|
19
|
+
if (style) {
|
20
|
+
UnistylesShadowRegistry
|
21
|
+
.add(ref, style)
|
22
|
+
.then(newClassNames => {
|
23
|
+
if (equal(classNames, newClassNames)) {
|
24
|
+
return
|
25
|
+
}
|
26
|
+
|
27
|
+
setClassNames(newClassNames)
|
28
|
+
})
|
29
|
+
}
|
30
|
+
|
31
|
+
useEffect(() => () => {
|
32
|
+
// Remove styles on unmount
|
33
|
+
UnistylesShadowRegistry.add(null, style)
|
34
|
+
})
|
35
|
+
|
36
|
+
return classNames
|
37
|
+
}
|
38
|
+
|
39
|
+
export const createUnistylesComponent = <TProps extends Record<string, any>, TMappings extends Partial<Omit<TProps, SupportedStyleProps>>>(Component: ComponentType<TProps>, mappings?: (theme: UnistylesTheme) => TMappings) => {
|
40
|
+
return (props: PartialBy<TProps, keyof TMappings | SupportedStyleProps>) => {
|
41
|
+
const [mappingsProps, setMappingsProps] = useState(mappings?.(UnistylesRuntime.getTheme()))
|
42
|
+
const styleClassNames = useShadowRegistry(props.style)
|
43
|
+
const contentContainerStyleClassNames = useShadowRegistry(props.contentContainerStyle)
|
44
|
+
|
45
|
+
useEffect(() => {
|
46
|
+
const disposeMappings = UnistylesListener.addListeners(ALL_DEPENDENCIES, () => {
|
47
|
+
if (!mappings) {
|
48
|
+
disposeMappings()
|
49
|
+
|
50
|
+
return
|
51
|
+
}
|
52
|
+
|
53
|
+
return setMappingsProps(mappings(UnistylesRuntime.getTheme()))
|
54
|
+
})
|
55
|
+
|
56
|
+
return () => disposeMappings()
|
57
|
+
}, [mappingsProps, props.style])
|
58
|
+
|
59
|
+
const combinedProps = {
|
60
|
+
...mappingsProps,
|
61
|
+
...props,
|
62
|
+
...props.style ? {
|
63
|
+
style: {
|
64
|
+
$$css: true,
|
65
|
+
'unistyles': styleClassNames.join(' ')
|
66
|
+
},
|
67
|
+
} : {},
|
68
|
+
...props.contentContainerStyle ? {
|
69
|
+
style: {
|
70
|
+
$$css: true,
|
71
|
+
'unistyles': contentContainerStyleClassNames.join(' ')
|
72
|
+
},
|
73
|
+
} : {},
|
74
|
+
} as unknown as TProps
|
7
75
|
|
8
|
-
|
9
|
-
return (props: ComponentProps<T>) => {
|
10
|
-
return <Component {...props} />
|
76
|
+
return <Component {...combinedProps} />
|
11
77
|
}
|
12
78
|
}
|
@@ -32,6 +32,11 @@ HybridShadowRegistry.add = (handle, style, variants, args) => {
|
|
32
32
|
return
|
33
33
|
}
|
34
34
|
|
35
|
+
// don't register Reanimated styles
|
36
|
+
if (style?.initial?.updater) {
|
37
|
+
return
|
38
|
+
}
|
39
|
+
|
35
40
|
HybridShadowRegistry.link(findShadowNodeForHandle(handle), style, variants ?? {}, args ?? [])
|
36
41
|
}
|
37
42
|
|
package/src/types/common.ts
CHANGED
package/src/web/convert/index.ts
CHANGED
@@ -2,16 +2,15 @@ import type { UnistylesValues } from '../../types'
|
|
2
2
|
import { isPseudo } from './pseudo'
|
3
3
|
import { getStyle } from './style'
|
4
4
|
import { deepMergeObjects } from '../utils'
|
5
|
-
import { getTransformStyle } from './
|
6
|
-
import {
|
7
|
-
import { getTextShadowStyle } from './
|
8
|
-
import { getBoxShadowStyle } from './boxShadow'
|
5
|
+
import { getTransformStyle, getBoxShadow, getFilterStyle } from './object'
|
6
|
+
import { isShadow, isFilter, isTextShadow, isTransform, isBoxShadow } from './utils'
|
7
|
+
import { getTextShadowStyle, getBoxShadowStyle } from './shadow'
|
9
8
|
|
10
9
|
export const convertUnistyles = (value: UnistylesValues) => {
|
11
10
|
// Flag to mark if textShadow is already created
|
12
11
|
let hasTextShadow = false
|
13
12
|
// Flag to mark if boxShadow is already created
|
14
|
-
let
|
13
|
+
let hasShadow = false
|
15
14
|
|
16
15
|
const stylesArray = Object.entries({
|
17
16
|
...value,
|
@@ -40,17 +39,25 @@ export const convertUnistyles = (value: UnistylesValues) => {
|
|
40
39
|
return getTextShadowStyle(value)
|
41
40
|
}
|
42
41
|
|
43
|
-
//
|
44
|
-
if (
|
45
|
-
if (
|
42
|
+
// RN shadows
|
43
|
+
if (isShadow(unistylesKey)) {
|
44
|
+
if (hasShadow) {
|
46
45
|
return []
|
47
46
|
}
|
48
47
|
|
49
|
-
|
48
|
+
hasShadow = true
|
50
49
|
|
51
50
|
return getBoxShadowStyle(value)
|
52
51
|
}
|
53
52
|
|
53
|
+
if (isFilter(unistylesKey, unistylesValue)) {
|
54
|
+
return getFilterStyle(unistylesValue)
|
55
|
+
}
|
56
|
+
|
57
|
+
if (isBoxShadow(unistylesKey, unistylesValue)) {
|
58
|
+
return getBoxShadow(unistylesValue)
|
59
|
+
}
|
60
|
+
|
54
61
|
// Transforms
|
55
62
|
if (isTransform(unistylesKey, unistylesValue)) {
|
56
63
|
return getTransformStyle(unistylesValue)
|
@@ -0,0 +1,54 @@
|
|
1
|
+
import type { BoxShadowValue } from 'react-native'
|
2
|
+
import { normalizeNumericValue } from '../utils'
|
3
|
+
import { deepMergeObjects, keyInObject } from '../../utils'
|
4
|
+
|
5
|
+
const createBoxShadowValue = (style: BoxShadowValue) => {
|
6
|
+
const { offsetX, offsetY, blurRadius = 0, spreadDistance = 0, color = '#000', inset } = style
|
7
|
+
|
8
|
+
return `${inset ? 'inset ' : ''}${normalizeNumericValue(offsetX)} ${normalizeNumericValue(offsetY)} ${normalizeNumericValue(blurRadius as number)} ${normalizeNumericValue(spreadDistance as number)} ${color}`
|
9
|
+
}
|
10
|
+
|
11
|
+
export const getBoxShadow = (boxShadow: Array<BoxShadowValue>) => {
|
12
|
+
const breakpoints = new Set<string>()
|
13
|
+
boxShadow.forEach(shadow => {
|
14
|
+
const [key] = Object.keys(shadow)
|
15
|
+
const value = shadow[key as keyof BoxShadowValue]
|
16
|
+
|
17
|
+
// Breakpoints
|
18
|
+
if (typeof value === 'object') {
|
19
|
+
Object.keys(value).forEach(breakpoint => breakpoints.add(breakpoint))
|
20
|
+
}
|
21
|
+
})
|
22
|
+
|
23
|
+
if (breakpoints.size === 0) {
|
24
|
+
const boxShadowStyle = Object.fromEntries(boxShadow.map(shadow => {
|
25
|
+
const [key] = Object.keys(shadow)
|
26
|
+
return [key, shadow[key as keyof BoxShadowValue]]
|
27
|
+
}))
|
28
|
+
|
29
|
+
return {
|
30
|
+
boxShadow: createBoxShadowValue(boxShadowStyle)
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
const breakpointStyles = Array.from(breakpoints).map(breakpoint => {
|
35
|
+
const styles = Object.fromEntries(boxShadow.map(shadow => {
|
36
|
+
const [key] = Object.keys(shadow)
|
37
|
+
const value = shadow[key as keyof BoxShadowValue]
|
38
|
+
|
39
|
+
if (typeof value === 'object' && keyInObject(value, breakpoint)) {
|
40
|
+
return [key, value[breakpoint]]
|
41
|
+
}
|
42
|
+
|
43
|
+
return [key, value]
|
44
|
+
}))
|
45
|
+
|
46
|
+
return {
|
47
|
+
[breakpoint]: {
|
48
|
+
boxShadow: createBoxShadowValue(styles)
|
49
|
+
}
|
50
|
+
}
|
51
|
+
})
|
52
|
+
|
53
|
+
return deepMergeObjects(...breakpointStyles)
|
54
|
+
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import type { DropShadowValue } from 'react-native'
|
2
|
+
import { hyphenate } from '../../utils'
|
3
|
+
import type { Filters } from '../types'
|
4
|
+
import { getObjectStyle } from './objectStyle'
|
5
|
+
import { normalizeColor, normalizeNumericValue } from '../utils'
|
6
|
+
import { UnistylesRuntime } from '../../runtime'
|
7
|
+
import { isUnistylesMq } from '../../../mq'
|
8
|
+
|
9
|
+
const getDropShadowStyle = (dropShadow: DropShadowValue) => {
|
10
|
+
const { offsetX = 0, offsetY = 0, standardDeviation = 0, color = '#000' } = dropShadow
|
11
|
+
|
12
|
+
return `${normalizeColor(String(color))} ${normalizeNumericValue(offsetX)} ${normalizeNumericValue(offsetY)} ${normalizeNumericValue(standardDeviation)}`
|
13
|
+
}
|
14
|
+
|
15
|
+
export const getFilterStyle = (filters: Array<Filters>) => {
|
16
|
+
const restFilters = filters.filter(filter => Object.keys(filter)[0] !== 'dropShadow')
|
17
|
+
const dropShadow = (() => {
|
18
|
+
const dropShadowValue = filters.find(filter => Object.keys(filter)[0] === 'dropShadow')?.dropShadow as Record<string, any>
|
19
|
+
|
20
|
+
if (typeof dropShadowValue !== 'object') {
|
21
|
+
return []
|
22
|
+
}
|
23
|
+
|
24
|
+
const breakpoints = Object.keys(dropShadowValue).filter(key => Object.keys(UnistylesRuntime.breakpoints).includes(key) || isUnistylesMq(key))
|
25
|
+
const breakpointsDropShadow = Object.fromEntries(breakpoints.map(breakpoint => [breakpoint, getDropShadowStyle(dropShadowValue[breakpoint])]))
|
26
|
+
|
27
|
+
if (breakpoints.length === 0) {
|
28
|
+
return [{
|
29
|
+
dropShadow: getDropShadowStyle(dropShadowValue as DropShadowValue)
|
30
|
+
}]
|
31
|
+
}
|
32
|
+
|
33
|
+
return [{
|
34
|
+
dropShadow: breakpointsDropShadow
|
35
|
+
}]
|
36
|
+
})()
|
37
|
+
|
38
|
+
return getObjectStyle([...restFilters, ...dropShadow], 'filter', (key, value) => `${hyphenate(key)}(${normalizeNumericValue(value as number | string)})`)
|
39
|
+
}
|
@@ -0,0 +1,68 @@
|
|
1
|
+
import { deepMergeObjects, keyInObject } from '../../utils'
|
2
|
+
|
3
|
+
type Styles = Record<string, any>
|
4
|
+
type Normalize<TStyles extends Styles> = (key: keyof TStyles, value: TStyles[keyof TStyles]) => any
|
5
|
+
|
6
|
+
const createStylesValue = <TStyles extends Styles>(styles: Array<TStyles>, normalize: Normalize<TStyles>) => styles
|
7
|
+
.map(style => {
|
8
|
+
const [key] = Object.keys(style)
|
9
|
+
|
10
|
+
if (!key) {
|
11
|
+
return undefined
|
12
|
+
}
|
13
|
+
|
14
|
+
return normalize(key, style[key])
|
15
|
+
})
|
16
|
+
.filter(Boolean)
|
17
|
+
.join(' ')
|
18
|
+
|
19
|
+
export const getObjectStyle = <TStyles extends Styles>(styles: Array<TStyles>, styleKey: string, normalize: Normalize<TStyles>) => {
|
20
|
+
const breakpoints = new Set<string>()
|
21
|
+
const normalStyles: Array<TStyles> = []
|
22
|
+
|
23
|
+
styles.forEach(style => {
|
24
|
+
const [property] = Object.keys(style)
|
25
|
+
|
26
|
+
if (!property) {
|
27
|
+
return
|
28
|
+
}
|
29
|
+
|
30
|
+
const value = style[property]
|
31
|
+
|
32
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
33
|
+
Object.keys(value ?? {}).forEach(breakpoint => breakpoints.add(breakpoint))
|
34
|
+
|
35
|
+
return
|
36
|
+
}
|
37
|
+
|
38
|
+
normalStyles.push(style)
|
39
|
+
})
|
40
|
+
|
41
|
+
const breakpointStyles = Array.from(breakpoints).flatMap(breakpoint => {
|
42
|
+
const stylesPerBreakpoint = styles.flatMap(style => {
|
43
|
+
const [property] = Object.keys(style)
|
44
|
+
|
45
|
+
if (!property) {
|
46
|
+
return []
|
47
|
+
}
|
48
|
+
|
49
|
+
const value = style[property]
|
50
|
+
|
51
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
52
|
+
return keyInObject(value, breakpoint) ? [{ [property]: value[breakpoint] }] : []
|
53
|
+
}
|
54
|
+
|
55
|
+
return []
|
56
|
+
}) as Array<TStyles>
|
57
|
+
|
58
|
+
return [{
|
59
|
+
[breakpoint]: {
|
60
|
+
[styleKey]: createStylesValue(stylesPerBreakpoint, normalize)
|
61
|
+
}
|
62
|
+
}]
|
63
|
+
})
|
64
|
+
|
65
|
+
return deepMergeObjects<Record<string, any>>({
|
66
|
+
[styleKey]: createStylesValue(normalStyles, normalize)
|
67
|
+
}, ...breakpointStyles)
|
68
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import { getObjectStyle } from './objectStyle'
|
2
|
+
import { normalizeNumericValue } from '../utils'
|
3
|
+
import type { TransformStyles } from '../../../types/core'
|
4
|
+
|
5
|
+
const normalizeTransform = (key: string, value: any) => {
|
6
|
+
if (key.includes('scale')) {
|
7
|
+
return value
|
8
|
+
}
|
9
|
+
|
10
|
+
if (typeof value === 'number') {
|
11
|
+
return normalizeNumericValue(value)
|
12
|
+
}
|
13
|
+
|
14
|
+
return value
|
15
|
+
}
|
16
|
+
|
17
|
+
export const getTransformStyle = (transforms: Array<TransformStyles>) => getObjectStyle(transforms, 'transform', (key, value) => {
|
18
|
+
switch(key) {
|
19
|
+
case 'matrix':
|
20
|
+
return `${key}(${(value as Array<number>).join(',')})`
|
21
|
+
default:
|
22
|
+
return `${key}(${normalizeTransform(key, value)})`
|
23
|
+
}
|
24
|
+
})
|
@@ -1,41 +1,20 @@
|
|
1
|
-
import { deepMergeObjects
|
2
|
-
import {
|
3
|
-
import {
|
4
|
-
import {
|
1
|
+
import { deepMergeObjects } from '../../utils'
|
2
|
+
import { BOX_SHADOW_STYLES, type BoxShadow } from '../types'
|
3
|
+
import { extractShadowValue, normalizeColor, normalizeNumericValue } from '../utils'
|
4
|
+
import { getShadowBreakpoints } from './getShadowBreakpoints'
|
5
5
|
|
6
6
|
const createBoxShadowValue = (style: BoxShadow) => {
|
7
|
-
// at this point every prop is present
|
8
7
|
const { shadowColor, shadowOffset, shadowOpacity, shadowRadius } = style
|
9
|
-
const offsetX = normalizeNumericValue(shadowOffset
|
10
|
-
const offsetY = normalizeNumericValue(shadowOffset
|
11
|
-
const radius = normalizeNumericValue(shadowRadius)
|
12
|
-
const color = normalizeColor(shadowColor as string, shadowOpacity as number)
|
8
|
+
const offsetX = normalizeNumericValue(shadowOffset?.width ?? 0)
|
9
|
+
const offsetY = normalizeNumericValue(shadowOffset?.height ?? 0)
|
10
|
+
const radius = normalizeNumericValue(shadowRadius ?? 0)
|
11
|
+
const color = normalizeColor((shadowColor ?? '#000000') as string, (shadowOpacity ?? 1) as number)
|
13
12
|
|
14
13
|
return `${offsetX} ${offsetY} ${radius} ${color}`
|
15
14
|
}
|
16
15
|
|
17
16
|
export const getBoxShadowStyle = (styles: Record<string, any>) => {
|
18
|
-
const
|
19
|
-
|
20
|
-
if (missingStyles.length) {
|
21
|
-
warn(`can't apply box shadow as you miss these properties: ${missingStyles.join(', ')}`)
|
22
|
-
|
23
|
-
return {}
|
24
|
-
}
|
25
|
-
|
26
|
-
const breakpointsSet = new Set<string>()
|
27
|
-
|
28
|
-
try {
|
29
|
-
validateShadow(BOX_SHADOW_STYLES, styles, breakpointsSet)
|
30
|
-
} catch (error) {
|
31
|
-
if (typeof error === 'string') {
|
32
|
-
warn(error)
|
33
|
-
}
|
34
|
-
|
35
|
-
return {}
|
36
|
-
}
|
37
|
-
|
38
|
-
const breakpoints = Array.from(breakpointsSet)
|
17
|
+
const breakpoints = getShadowBreakpoints(BOX_SHADOW_STYLES, styles)
|
39
18
|
|
40
19
|
// If no breakpoints were used return styles without media queries
|
41
20
|
if (breakpoints.length === 0) {
|