react-native-unistyles 3.6.0 → 3.7.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 +4 -9
- package/android/build.gradle +42 -0
- package/android/src/legacy/java/com/unistyles/NativePlatform+extraWindows.kt +16 -0
- package/android/src/main/cxx/NativeUnistylesModule.cpp +5 -11
- package/android/src/main/cxx/NativeUnistylesModule.h +0 -4
- package/android/src/main/java/com/unistyles/NativePlatform+android.kt +82 -39
- package/android/src/main/java/com/unistyles/NativePlatform+insets.kt +73 -0
- package/android/src/main/java/com/unistyles/UnistylesModule.kt +2 -13
- package/android/src/rn86/java/com/unistyles/NativePlatform+extraWindows.kt +28 -0
- package/cxx/common/PerformanceTracing.h +85 -0
- package/cxx/converters/BackgroundLayerConverter.cpp +523 -0
- package/cxx/converters/BackgroundLayerConverter.h +14 -0
- package/cxx/converters/FontVariationSettingsConverter.cpp +104 -0
- package/cxx/converters/FontVariationSettingsConverter.h +17 -0
- package/cxx/core/UnistyleWrapper.h +16 -1
- package/cxx/hybridObjects/HybridShadowRegistry.cpp +8 -0
- package/cxx/hybridObjects/HybridStyleSheet.cpp +11 -0
- package/cxx/hybridObjects/HybridStyleSheet.h +1 -0
- package/cxx/hybridObjects/HybridUnistylesRuntime.cpp +10 -30
- package/cxx/hybridObjects/HybridUnistylesRuntime.h +2 -2
- package/cxx/parser/Parser.cpp +75 -10
- package/cxx/shadowTree/ShadowTreeDiagnostics.cpp +74 -0
- package/cxx/shadowTree/ShadowTreeManager.cpp +3 -0
- package/lib/commonjs/components/NamedTheme.js +4 -4
- package/lib/commonjs/components/NamedTheme.js.map +1 -1
- package/lib/commonjs/components/ScopedThemeContext.js +3 -1
- package/lib/commonjs/components/ScopedThemeContext.js.map +1 -1
- package/lib/commonjs/core/createUnistylesImageBackground.js +6 -2
- package/lib/commonjs/core/createUnistylesImageBackground.js.map +1 -1
- package/lib/commonjs/core/withUnistyles/withUnistyles.js +10 -7
- package/lib/commonjs/core/withUnistyles/withUnistyles.js.map +1 -1
- package/lib/commonjs/core/withUnistyles/withUnistyles.native.js +22 -3
- package/lib/commonjs/core/withUnistyles/withUnistyles.native.js.map +1 -1
- package/lib/commonjs/mocks.js +27 -3
- package/lib/commonjs/mocks.js.map +1 -1
- package/lib/commonjs/specs/ShadowRegistry/index.js +13 -3
- package/lib/commonjs/specs/ShadowRegistry/index.js.map +1 -1
- package/lib/commonjs/specs/ShadowRegistry/tracing.js +26 -0
- package/lib/commonjs/specs/ShadowRegistry/tracing.js.map +1 -0
- package/lib/commonjs/utils.js +52 -1
- package/lib/commonjs/utils.js.map +1 -1
- package/lib/commonjs/web/convert/index.js +19 -1
- package/lib/commonjs/web/convert/index.js.map +1 -1
- package/lib/commonjs/web/convert/module.d.ts +3 -0
- package/lib/commonjs/web/convert/object/backgroundLayers.js +30 -0
- package/lib/commonjs/web/convert/object/backgroundLayers.js.map +1 -0
- package/lib/commonjs/web/convert/object/fontVariationSettings.js +12 -0
- package/lib/commonjs/web/convert/object/fontVariationSettings.js.map +1 -0
- package/lib/commonjs/web/convert/object/index.js +22 -0
- package/lib/commonjs/web/convert/object/index.js.map +1 -1
- package/lib/commonjs/web/convert/utils.js +7 -1
- package/lib/commonjs/web/convert/utils.js.map +1 -1
- package/lib/commonjs/web/registry.js +6 -4
- package/lib/commonjs/web/registry.js.map +1 -1
- package/lib/commonjs/web/runtime.js +9 -6
- package/lib/commonjs/web/runtime.js.map +1 -1
- package/lib/commonjs/web/utils/unistyle.js +1 -3
- package/lib/commonjs/web/utils/unistyle.js.map +1 -1
- package/lib/module/components/NamedTheme.js +4 -4
- package/lib/module/components/NamedTheme.js.map +1 -1
- package/lib/module/components/ScopedThemeContext.js +3 -1
- package/lib/module/components/ScopedThemeContext.js.map +1 -1
- package/lib/module/core/createUnistylesImageBackground.js +6 -2
- package/lib/module/core/createUnistylesImageBackground.js.map +1 -1
- package/lib/module/core/withUnistyles/withUnistyles.js +9 -6
- package/lib/module/core/withUnistyles/withUnistyles.js.map +1 -1
- package/lib/module/core/withUnistyles/withUnistyles.native.js +24 -5
- package/lib/module/core/withUnistyles/withUnistyles.native.js.map +1 -1
- package/lib/module/mocks.js +27 -3
- package/lib/module/mocks.js.map +1 -1
- package/lib/module/specs/ShadowRegistry/index.js +13 -3
- package/lib/module/specs/ShadowRegistry/index.js.map +1 -1
- package/lib/module/specs/ShadowRegistry/tracing.js +21 -0
- package/lib/module/specs/ShadowRegistry/tracing.js.map +1 -0
- package/lib/module/utils.js +50 -0
- package/lib/module/utils.js.map +1 -1
- package/lib/module/web/convert/index.js +22 -3
- package/lib/module/web/convert/index.js.map +1 -1
- package/lib/module/web/convert/module.d.ts +3 -0
- package/lib/module/web/convert/object/backgroundLayers.js +25 -0
- package/lib/module/web/convert/object/backgroundLayers.js.map +1 -0
- package/lib/module/web/convert/object/fontVariationSettings.js +7 -0
- package/lib/module/web/convert/object/fontVariationSettings.js.map +1 -0
- package/lib/module/web/convert/object/index.js +2 -0
- package/lib/module/web/convert/object/index.js.map +1 -1
- package/lib/module/web/convert/utils.js +4 -0
- package/lib/module/web/convert/utils.js.map +1 -1
- package/lib/module/web/registry.js +6 -4
- package/lib/module/web/registry.js.map +1 -1
- package/lib/module/web/runtime.js +9 -6
- package/lib/module/web/runtime.js.map +1 -1
- package/lib/module/web/utils/unistyle.js +2 -4
- package/lib/module/web/utils/unistyle.js.map +1 -1
- package/lib/typescript/src/components/ScopedThemeContext.d.ts +2 -1
- package/lib/typescript/src/components/ScopedThemeContext.d.ts.map +1 -1
- package/lib/typescript/src/core/createUnistylesImageBackground.d.ts.map +1 -1
- package/lib/typescript/src/core/withUnistyles/withUnistyles.d.ts +6 -3
- package/lib/typescript/src/core/withUnistyles/withUnistyles.d.ts.map +1 -1
- package/lib/typescript/src/core/withUnistyles/withUnistyles.native.d.ts +7 -4
- package/lib/typescript/src/core/withUnistyles/withUnistyles.native.d.ts.map +1 -1
- package/lib/typescript/src/specs/ShadowRegistry/index.d.ts.map +1 -1
- package/lib/typescript/src/specs/ShadowRegistry/tracing.d.ts +2 -0
- package/lib/typescript/src/specs/ShadowRegistry/tracing.d.ts.map +1 -0
- package/lib/typescript/src/utils.d.ts +1 -0
- package/lib/typescript/src/utils.d.ts.map +1 -1
- package/lib/typescript/src/web/convert/index.d.ts.map +1 -1
- package/lib/typescript/src/web/convert/object/backgroundLayers.d.ts +4 -0
- package/lib/typescript/src/web/convert/object/backgroundLayers.d.ts.map +1 -0
- package/lib/typescript/src/web/convert/object/fontVariationSettings.d.ts +4 -0
- package/lib/typescript/src/web/convert/object/fontVariationSettings.d.ts.map +1 -0
- package/lib/typescript/src/web/convert/object/index.d.ts +2 -0
- package/lib/typescript/src/web/convert/object/index.d.ts.map +1 -1
- package/lib/typescript/src/web/convert/utils.d.ts +2 -0
- package/lib/typescript/src/web/convert/utils.d.ts.map +1 -1
- 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/utils/unistyle.d.ts.map +1 -1
- package/metro/babel-transformer.js +79 -17
- package/package.json +26 -26
- package/plugin/index.js +79 -17
- package/src/components/NamedTheme.tsx +5 -5
- package/src/components/ScopedThemeContext.ts +6 -2
- package/src/core/createUnistylesImageBackground.tsx +6 -2
- package/src/core/withUnistyles/withUnistyles.native.tsx +28 -6
- package/src/core/withUnistyles/withUnistyles.tsx +6 -6
- package/src/mocks.ts +14 -5
- package/src/specs/ShadowRegistry/index.ts +14 -3
- package/src/specs/ShadowRegistry/tracing.ts +23 -0
- package/src/utils.ts +51 -0
- package/src/web/convert/index.ts +39 -3
- package/src/web/convert/object/backgroundLayers.ts +33 -0
- package/src/web/convert/object/fontVariationSettings.ts +7 -0
- package/src/web/convert/object/index.ts +2 -0
- package/src/web/convert/utils.ts +11 -0
- package/src/web/registry.ts +7 -8
- package/src/web/runtime.ts +7 -7
- package/src/web/utils/unistyle.ts +2 -4
- package/lib/commonjs/web/convert/module.d.js +0 -2
- package/lib/commonjs/web/convert/module.d.js.map +0 -1
- package/lib/module/web/convert/module.d.js +0 -2
- package/lib/module/web/convert/module.d.js.map +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React, {
|
|
2
|
-
forwardRef,
|
|
3
2
|
useContext,
|
|
4
3
|
useEffect,
|
|
5
4
|
type ComponentProps,
|
|
6
5
|
type ComponentRef,
|
|
7
6
|
type ComponentType,
|
|
7
|
+
type Ref,
|
|
8
8
|
} from 'react'
|
|
9
9
|
|
|
10
10
|
import type { UnistylesValues } from '../../types'
|
|
@@ -12,7 +12,7 @@ import type { Mappings } from './types'
|
|
|
12
12
|
|
|
13
13
|
import { ScopedThemeContext } from '../../components/ScopedThemeContext'
|
|
14
14
|
import { type UnistyleDependency, UnistylesShadowRegistry } from '../../specs'
|
|
15
|
-
import { deepMergeObjects } from '../../utils'
|
|
15
|
+
import { deepMergeObjects, isAnimatedStyleHandle } from '../../utils'
|
|
16
16
|
import { useProxifiedUnistyles } from '../useProxifiedUnistyles'
|
|
17
17
|
import { maybeWarnAboutMultipleUnistyles } from '../warn'
|
|
18
18
|
|
|
@@ -27,10 +27,30 @@ type UnistylesSecrets = {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
type MappedSecrets = {
|
|
30
|
-
styles: Record<string, any>
|
|
30
|
+
styles: Record<string, any> | Array<Record<string, any>>
|
|
31
31
|
dependencies: Array<UnistyleDependency>
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
// Reanimated finds animated styles by their keys, merged with other styles they would hide them
|
|
35
|
+
// so keep every animated style as a separate entry and merge only the styles between them, in order
|
|
36
|
+
const mergeAroundAnimatedStyles = (secrets: Array<UnistylesSecrets>) =>
|
|
37
|
+
secrets.reduce<Array<Record<string, any>>>((acc, secret) => {
|
|
38
|
+
const style = secret.uni__getStyles()
|
|
39
|
+
const lastStyle = acc.at(-1)
|
|
40
|
+
|
|
41
|
+
if (isAnimatedStyleHandle(style)) {
|
|
42
|
+
return acc.concat([style])
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (lastStyle && !isAnimatedStyleHandle(lastStyle)) {
|
|
46
|
+
Object.assign(lastStyle, style)
|
|
47
|
+
|
|
48
|
+
return acc
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return acc.concat([{ ...style }])
|
|
52
|
+
}, [])
|
|
53
|
+
|
|
34
54
|
export const getSecrets = (styleProps: Record<string, any> = {}): MappedSecrets => {
|
|
35
55
|
const styles = Array.isArray(styleProps) ? styleProps.flat(Infinity) : [styleProps]
|
|
36
56
|
|
|
@@ -48,7 +68,9 @@ export const getSecrets = (styleProps: Record<string, any> = {}): MappedSecrets
|
|
|
48
68
|
}, [])
|
|
49
69
|
|
|
50
70
|
return {
|
|
51
|
-
styles:
|
|
71
|
+
styles: styles.some(isAnimatedStyleHandle)
|
|
72
|
+
? mergeAroundAnimatedStyles(secrets)
|
|
73
|
+
: secrets.reduce((acc, secret) => Object.assign(acc, secret.uni__getStyles()), {} as Record<string, any>),
|
|
52
74
|
dependencies: secrets.flatMap((secret) => secret.uni__dependencies),
|
|
53
75
|
}
|
|
54
76
|
}
|
|
@@ -66,7 +88,7 @@ export const withUnistyles = <TComponent, TMappings extends GenericComponentProp
|
|
|
66
88
|
contentContainerStyle?: UnistylesValues
|
|
67
89
|
}
|
|
68
90
|
|
|
69
|
-
return
|
|
91
|
+
return ({ ref, ...props }: PropsWithUnistyles & { ref?: Ref<GenericComponentRef<TComponent>> }) => {
|
|
70
92
|
const narrowedProps = props as PropsWithUnistyles & UnistyleStyles
|
|
71
93
|
const NativeComponent = Component as ComponentType
|
|
72
94
|
|
|
@@ -127,5 +149,5 @@ export const withUnistyles = <TComponent, TMappings extends GenericComponentProp
|
|
|
127
149
|
} as any
|
|
128
150
|
|
|
129
151
|
return <NativeComponent key={uniPropsKey || mappingsKey} {...finalProps} ref={ref} />
|
|
130
|
-
}
|
|
152
|
+
}
|
|
131
153
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { type ComponentType,
|
|
1
|
+
import React, { type ComponentType, type ComponentProps, type ComponentRef, type Ref } from 'react'
|
|
2
2
|
|
|
3
3
|
import type { UnistylesValues } from '../../types'
|
|
4
4
|
import type { Mappings } from './types'
|
|
@@ -26,9 +26,9 @@ export const withUnistyles = <TComponent, TMappings extends GenericComponentProp
|
|
|
26
26
|
contentContainerStyle?: UnistylesValues
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
return
|
|
29
|
+
return ({ ref, ...props }: PropsWithUnistyles & { ref?: Ref<GenericComponentRef<TComponent>> }) => {
|
|
30
30
|
const narrowedProps = props as PropsWithUnistyles & UnistyleStyles
|
|
31
|
-
const
|
|
31
|
+
const [classNames, animatedStyles] = getClassName(narrowedProps.style, true) ?? []
|
|
32
32
|
const contentContainerStyleClassNames = getClassName(narrowedProps.contentContainerStyle)
|
|
33
33
|
const { proxifiedRuntime, proxifiedTheme } = useProxifiedUnistyles()
|
|
34
34
|
|
|
@@ -50,7 +50,8 @@ export const withUnistyles = <TComponent, TMappings extends GenericComponentProp
|
|
|
50
50
|
...(narrowedProps.style
|
|
51
51
|
? {
|
|
52
52
|
// Override default component styles with undefined values to reset them
|
|
53
|
-
|
|
53
|
+
// animated styles can't be a class, so they stay inline
|
|
54
|
+
style: animatedStyles?.length ? [emptyStyles, ...animatedStyles] : emptyStyles,
|
|
54
55
|
}
|
|
55
56
|
: {}),
|
|
56
57
|
...(narrowedProps.contentContainerStyle
|
|
@@ -68,12 +69,11 @@ export const withUnistyles = <TComponent, TMappings extends GenericComponentProp
|
|
|
68
69
|
maybeWarnAboutMultipleUnistyles(narrowedProps.contentContainerStyle, `withUnistyles(${Component.displayName ?? Component.name ?? 'Unknown'})`)
|
|
69
70
|
|
|
70
71
|
const NativeComponent = Component as ComponentType
|
|
71
|
-
const [classNames] = styleClassNames ?? []
|
|
72
72
|
|
|
73
73
|
return (
|
|
74
74
|
<div className={classNames?.hash} style={{ display: 'contents' }}>
|
|
75
75
|
<NativeComponent key={uniPropsKey || mappingsKey} {...combinedProps} ref={ref} />
|
|
76
76
|
</div>
|
|
77
77
|
)
|
|
78
|
-
}
|
|
78
|
+
}
|
|
79
79
|
}
|
package/src/mocks.ts
CHANGED
|
@@ -20,6 +20,7 @@ jest.mock('react-native-nitro-modules', () => ({
|
|
|
20
20
|
createHybridObject: () => ({
|
|
21
21
|
add: () => {},
|
|
22
22
|
init: () => {},
|
|
23
|
+
addChangeListener: () => () => {},
|
|
23
24
|
createHybridStatusBar: () => ({
|
|
24
25
|
setStyle: () => {},
|
|
25
26
|
}),
|
|
@@ -199,11 +200,19 @@ jest.mock('react-native-unistyles', () => {
|
|
|
199
200
|
Component: TComponent,
|
|
200
201
|
mapper?: (theme: UnistylesTheme, runtime: typeof miniRuntime) => TComponent,
|
|
201
202
|
) =>
|
|
202
|
-
(props: any) =>
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
})
|
|
203
|
+
({ uniProps, ...props }: any) => {
|
|
204
|
+
const { deepMergeObjects } = require('./utils')
|
|
205
|
+
const theme = (Object.values(_REGISTRY.themes).at(0) ?? {}) as UnistylesTheme
|
|
206
|
+
const { key: mappingsKey, ...mappingsProps } = mapper?.(theme, miniRuntime) ?? ({} as any)
|
|
207
|
+
const { key: uniPropsKey, ...unistyleProps } = uniProps?.(theme, miniRuntime) ?? {}
|
|
208
|
+
|
|
209
|
+
return React.createElement(Component, {
|
|
210
|
+
...deepMergeObjects(mappingsProps, unistyleProps, props),
|
|
211
|
+
...(props.style ? { style: props.style } : {}),
|
|
212
|
+
...(props.contentContainerStyle ? { contentContainerStyle: props.contentContainerStyle } : {}),
|
|
213
|
+
key: uniPropsKey || mappingsKey,
|
|
214
|
+
})
|
|
215
|
+
},
|
|
207
216
|
mq: {
|
|
208
217
|
only: {
|
|
209
218
|
width: () => ({
|
|
@@ -9,6 +9,7 @@ import type { ShadowNode, Unistyle, ViewHandle } from './types'
|
|
|
9
9
|
import { Fiber, Reanimated } from '../../unifiber/src'
|
|
10
10
|
import { StyleSheet } from '../StyleSheet'
|
|
11
11
|
import { createUnistylesStyleSource } from './styleSource'
|
|
12
|
+
import { traceSection } from './tracing'
|
|
12
13
|
|
|
13
14
|
interface ShadowRegistry extends UnistylesShadowRegistrySpec {
|
|
14
15
|
// Babel API
|
|
@@ -74,7 +75,7 @@ const refreshReactNodes = () => {
|
|
|
74
75
|
HybridShadowRegistry.refreshReactNodes(refreshNodes)
|
|
75
76
|
}
|
|
76
77
|
|
|
77
|
-
owners.refresh(committedHosts)
|
|
78
|
+
traceSection('refreshOwners', () => owners.refresh(committedHosts))
|
|
78
79
|
} finally {
|
|
79
80
|
committedHosts.length = 0
|
|
80
81
|
refreshNodes = []
|
|
@@ -83,6 +84,16 @@ const refreshReactNodes = () => {
|
|
|
83
84
|
|
|
84
85
|
StyleSheet.addChangeListener(refreshReactNodes)
|
|
85
86
|
|
|
87
|
+
// a unistyle key holds its secrets object. A unistyle spread into another StyleSheet.create keeps its key,
|
|
88
|
+
// but the parser resolves the (hidden) secrets to undefined, so the key no longer points at a unistyle
|
|
89
|
+
const isUnistyleKey = (style: any, key: string) => {
|
|
90
|
+
if (!key.startsWith('unistyles_')) {
|
|
91
|
+
return false
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return typeof style[key] === 'object' && style[key] !== null
|
|
95
|
+
}
|
|
96
|
+
|
|
86
97
|
// skips empty styles and splits a style merged from many unistyles (eg. flattened by Animated) into one per unistyle
|
|
87
98
|
// runs for every style on every link, so it reads the keys once and allocates only for the rare merged style
|
|
88
99
|
const collectStyle = (style: any, collected: Array<any>) => {
|
|
@@ -94,7 +105,7 @@ const collectStyle = (style: any, collected: Array<any>) => {
|
|
|
94
105
|
let unistylesCount = 0
|
|
95
106
|
|
|
96
107
|
for (const key of keys) {
|
|
97
|
-
if (key
|
|
108
|
+
if (isUnistyleKey(style, key)) {
|
|
98
109
|
unistylesCount++
|
|
99
110
|
}
|
|
100
111
|
}
|
|
@@ -108,7 +119,7 @@ const collectStyle = (style: any, collected: Array<any>) => {
|
|
|
108
119
|
}
|
|
109
120
|
|
|
110
121
|
for (const key of keys) {
|
|
111
|
-
if (key
|
|
122
|
+
if (isUnistyleKey(style, key)) {
|
|
112
123
|
collected.push({ [key]: style[key] })
|
|
113
124
|
}
|
|
114
125
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// console.timeStamp(label, start, end, trackName), React Native 0.86+ reports it only while DevTools records and keeps
|
|
2
|
+
// nothing, unlike performance.measure, which adds every entry to an unbounded buffer
|
|
3
|
+
type TracingConsole = {
|
|
4
|
+
timeStamp?: (label: string, start: number, end: number, trackName: string) => void
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const tracingConsole = console as unknown as TracingConsole
|
|
8
|
+
const canTrace = __DEV__ && typeof tracingConsole.timeStamp === 'function'
|
|
9
|
+
|
|
10
|
+
// Slice on the "Unistyles" track of the React Native DevTools Performance panel, next to the native ones
|
|
11
|
+
export const traceSection = <T>(name: string, fn: () => T): T => {
|
|
12
|
+
if (!canTrace) {
|
|
13
|
+
return fn()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const start = performance.now()
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
return fn()
|
|
20
|
+
} finally {
|
|
21
|
+
tracingConsole.timeStamp?.(name, start, performance.now(), 'Unistyles')
|
|
22
|
+
}
|
|
23
|
+
}
|
package/src/utils.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
export const isDefined = <T>(value: T): value is NonNullable<T> => value !== undefined && value !== null
|
|
2
2
|
|
|
3
|
+
// Reanimated useAnimatedStyle handle, it's a plain object, not an Animated.Node
|
|
4
|
+
// styleUpdaterContainer was added in Reanimated 4.1, so check only the keys every version has
|
|
5
|
+
export const isAnimatedStyleHandle = (value: unknown): boolean =>
|
|
6
|
+
typeof value === 'object' && value !== null && 'viewDescriptors' in value && 'initial' in value
|
|
7
|
+
|
|
3
8
|
export const deepMergeObjects = <T extends Record<PropertyKey, any>>(...sources: Array<T>) => {
|
|
4
9
|
const target = {} as T
|
|
5
10
|
|
|
@@ -23,7 +28,53 @@ export const deepMergeObjects = <T extends Record<PropertyKey, any>>(...sources:
|
|
|
23
28
|
return target
|
|
24
29
|
}
|
|
25
30
|
|
|
31
|
+
// React tells a class component from a function component by these keys
|
|
32
|
+
const CLASS_PROTOTYPE_KEYS = ['isReactComponent', 'render']
|
|
33
|
+
const CLASS_STATIC_KEYS = ['contextType', 'contextTypes', 'childContextTypes', 'getDerivedStateFromProps']
|
|
34
|
+
|
|
35
|
+
// owner doesn't have the key, objects that inherit from owner read it from source
|
|
36
|
+
const hideFromOwner = (owner: object, source: object, key: string) => {
|
|
37
|
+
Object.defineProperty(owner, key, {
|
|
38
|
+
configurable: true,
|
|
39
|
+
get() {
|
|
40
|
+
return this === owner ? undefined : Reflect.get(source, key, this)
|
|
41
|
+
},
|
|
42
|
+
set(value) {
|
|
43
|
+
Object.defineProperty(this, key, { value, writable: true, enumerable: true, configurable: true })
|
|
44
|
+
},
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const inheritNativeClass = (Component: any, UnistylesComponent: (props: unknown) => unknown) => {
|
|
49
|
+
function UnistylesClassComponent(this: unknown, ...args: Array<unknown>) {
|
|
50
|
+
if (this instanceof UnistylesClassComponent) {
|
|
51
|
+
return Reflect.construct(Component, args, new.target ?? this.constructor)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return UnistylesComponent(args[0])
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
Object.setPrototypeOf(UnistylesClassComponent, Component)
|
|
58
|
+
UnistylesClassComponent.prototype = Object.create(Component.prototype, {
|
|
59
|
+
constructor: { value: UnistylesClassComponent, writable: true, configurable: true },
|
|
60
|
+
})
|
|
61
|
+
// only the keys of the class, eg. React warns about a subclass with a `contextType` key that isn't a context
|
|
62
|
+
CLASS_PROTOTYPE_KEYS.filter((key) => key in Component.prototype).forEach((key) =>
|
|
63
|
+
hideFromOwner(UnistylesClassComponent.prototype, Component.prototype, key),
|
|
64
|
+
)
|
|
65
|
+
CLASS_STATIC_KEYS.filter((key) => key in Component).forEach((key) =>
|
|
66
|
+
hideFromOwner(UnistylesClassComponent, Component, key),
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
return UnistylesClassComponent
|
|
70
|
+
}
|
|
71
|
+
|
|
26
72
|
export const copyComponentProperties = (Component: any, UnistylesComponent: any) => {
|
|
73
|
+
// static properties (eg. displayName) are inherited from the class
|
|
74
|
+
if (Component?.prototype?.isReactComponent && typeof UnistylesComponent === 'function') {
|
|
75
|
+
return inheritNativeClass(Component, UnistylesComponent)
|
|
76
|
+
}
|
|
77
|
+
|
|
27
78
|
Object.entries(Component).forEach(([key, value]) => {
|
|
28
79
|
// Filter out the keys we don't want to copy
|
|
29
80
|
if (['$$typeof', 'render', 'contextType'].includes(key)) {
|
package/src/web/convert/index.ts
CHANGED
|
@@ -2,11 +2,38 @@ import type { UnistylesValues } from '../../types'
|
|
|
2
2
|
import type { UnistylesRuntime } from '../runtime'
|
|
3
3
|
|
|
4
4
|
import { deepMergeObjects } from '../../utils'
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
getBackgroundLayers,
|
|
7
|
+
getBoxShadow,
|
|
8
|
+
getFilterStyle,
|
|
9
|
+
getFontVariationSettings,
|
|
10
|
+
getTransformStyle,
|
|
11
|
+
} from './object'
|
|
6
12
|
import { isPseudo } from './pseudo'
|
|
7
13
|
import { getBoxShadowStyle, getTextShadowStyle } from './shadow'
|
|
8
14
|
import { getStyle } from './style'
|
|
9
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
isBackgroundLayer,
|
|
17
|
+
isBoxShadow,
|
|
18
|
+
isFilter,
|
|
19
|
+
isFontVariationSettings,
|
|
20
|
+
isShadow,
|
|
21
|
+
isTextShadow,
|
|
22
|
+
isTransform,
|
|
23
|
+
} from './utils'
|
|
24
|
+
|
|
25
|
+
// a breakpoint can hold React Native's array or object syntax too
|
|
26
|
+
const getBreakpointStyle = (key: string, value: any) => {
|
|
27
|
+
if (isBackgroundLayer(key, value)) {
|
|
28
|
+
return getBackgroundLayers(key, value)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (isFontVariationSettings(key, value)) {
|
|
32
|
+
return getFontVariationSettings(value)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return getStyle(key, value)
|
|
36
|
+
}
|
|
10
37
|
|
|
11
38
|
export const convertUnistyles = (value: UnistylesValues, runtime: UnistylesRuntime) => {
|
|
12
39
|
// Flag to mark if textShadow is already created
|
|
@@ -65,10 +92,19 @@ export const convertUnistyles = (value: UnistylesValues, runtime: UnistylesRunti
|
|
|
65
92
|
return getTransformStyle(unistylesValue)
|
|
66
93
|
}
|
|
67
94
|
|
|
95
|
+
// React Native's array and object syntaxes, not breakpoints
|
|
96
|
+
if (isBackgroundLayer(unistylesKey, unistylesValue)) {
|
|
97
|
+
return getBackgroundLayers(unistylesKey, unistylesValue)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (isFontVariationSettings(unistylesKey, unistylesValue)) {
|
|
101
|
+
return getFontVariationSettings(unistylesValue)
|
|
102
|
+
}
|
|
103
|
+
|
|
68
104
|
// Breakpoints
|
|
69
105
|
if (typeof unistylesValue === 'object' && unistylesValue !== null) {
|
|
70
106
|
return Object.entries(unistylesValue).map(([breakpointKey, breakpointValue]) => {
|
|
71
|
-
return { [breakpointKey]:
|
|
107
|
+
return { [breakpointKey]: getBreakpointStyle(unistylesKey, breakpointValue) }
|
|
72
108
|
})
|
|
73
109
|
}
|
|
74
110
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { normalizeNumericValue } from '../utils'
|
|
2
|
+
|
|
3
|
+
type BackgroundLayerKey = 'backgroundSize' | 'backgroundPosition' | 'backgroundRepeat'
|
|
4
|
+
type BackgroundSize = string | { x: string | number; y: string | number }
|
|
5
|
+
type BackgroundPosition = Partial<Record<'top' | 'left' | 'right' | 'bottom', string | number>>
|
|
6
|
+
type BackgroundRepeat = { x: string; y: string }
|
|
7
|
+
|
|
8
|
+
const createBackgroundSizeValue = (size: BackgroundSize) => {
|
|
9
|
+
if (typeof size === 'string') {
|
|
10
|
+
return size
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return `${normalizeNumericValue(size.x)} ${normalizeNumericValue(size.y)}`
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const createBackgroundPositionValue = (position: BackgroundPosition) => {
|
|
17
|
+
const edges = (['left', 'right', 'top', 'bottom'] as const).filter((edge) => position[edge] !== undefined)
|
|
18
|
+
|
|
19
|
+
return edges.map((edge) => `${edge} ${normalizeNumericValue(position[edge]!)}`).join(' ')
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const createBackgroundRepeatValue = (repeat: BackgroundRepeat) => `${repeat.x} ${repeat.y}`
|
|
23
|
+
|
|
24
|
+
const createBackgroundLayerValue = {
|
|
25
|
+
backgroundSize: createBackgroundSizeValue,
|
|
26
|
+
backgroundPosition: createBackgroundPositionValue,
|
|
27
|
+
backgroundRepeat: createBackgroundRepeatValue,
|
|
28
|
+
} as Record<BackgroundLayerKey, (layer: any) => string>
|
|
29
|
+
|
|
30
|
+
// React Native's processed syntax, one object per background layer
|
|
31
|
+
export const getBackgroundLayers = (key: string, layers: Array<unknown>) => ({
|
|
32
|
+
[key]: layers.map(createBackgroundLayerValue[key as BackgroundLayerKey]).join(', '),
|
|
33
|
+
})
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Same output as React Native's processFontVariationSettings, eg. { wght: 700 } -> 'wght' 700
|
|
2
|
+
export const getFontVariationSettings = (fontVariationSettings: Record<string, number>) => ({
|
|
3
|
+
fontVariationSettings: Object.keys(fontVariationSettings)
|
|
4
|
+
.sort()
|
|
5
|
+
.map((axis) => `${axis.includes("'") ? `"${axis}"` : `'${axis}'`} ${fontVariationSettings[axis]}`)
|
|
6
|
+
.join(', '),
|
|
7
|
+
})
|
package/src/web/convert/utils.ts
CHANGED
|
@@ -21,6 +21,17 @@ export const isFilter = (key: string, value: any): value is Array<Filters> => ke
|
|
|
21
21
|
export const isBoxShadow = (key: string, value: any): value is Array<BoxShadowValue> =>
|
|
22
22
|
key === 'boxShadow' && Array.isArray(value)
|
|
23
23
|
|
|
24
|
+
export const isBackgroundLayer = (key: string, value: any): value is Array<unknown> =>
|
|
25
|
+
['backgroundSize', 'backgroundPosition', 'backgroundRepeat'].includes(key) && Array.isArray(value)
|
|
26
|
+
|
|
27
|
+
// { wght: 700 } is the object syntax, a breakpoints object holds strings or objects
|
|
28
|
+
export const isFontVariationSettings = (key: string, value: any): value is Record<string, number> =>
|
|
29
|
+
key === 'fontVariationSettings' &&
|
|
30
|
+
typeof value === 'object' &&
|
|
31
|
+
value !== null &&
|
|
32
|
+
!Array.isArray(value) &&
|
|
33
|
+
Object.values(value).every((axisValue) => typeof axisValue === 'number')
|
|
34
|
+
|
|
24
35
|
export const normalizeNumericValue = (value: number | string) =>
|
|
25
36
|
value && typeof value === 'number' ? `${value}px` : value
|
|
26
37
|
|
package/src/web/registry.ts
CHANGED
|
@@ -32,7 +32,7 @@ export class UnistylesRegistry {
|
|
|
32
32
|
)
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
return stylesheet(scopedTheme, this.services.runtime.
|
|
35
|
+
return stylesheet(scopedTheme, this.services.runtime.getMiniRuntime(scopedThemeName))
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
const computedStylesheet = this.stylesheets.get(stylesheet)
|
|
@@ -41,11 +41,9 @@ export class UnistylesRegistry {
|
|
|
41
41
|
return computedStylesheet
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
)
|
|
48
|
-
const createdStylesheet = stylesheet(currentTheme, this.services.runtime.miniRuntime)
|
|
44
|
+
const themeName = this.services.runtime.themeName
|
|
45
|
+
const currentTheme = this.services.runtime.getTheme(themeName, this.services.state.CSSVars)
|
|
46
|
+
const createdStylesheet = stylesheet(currentTheme, this.services.runtime.getMiniRuntime(themeName))
|
|
49
47
|
const dependencies = Object.values(createdStylesheet).flatMap((value) => extractUnistyleDependencies(value))
|
|
50
48
|
|
|
51
49
|
this.addDependenciesToStylesheet(stylesheet, dependencies)
|
|
@@ -65,9 +63,10 @@ export class UnistylesRegistry {
|
|
|
65
63
|
dependencies.forEach((dependency) => dependenciesMap.add(dependency))
|
|
66
64
|
|
|
67
65
|
const dispose = this.services.listener.addStylesheetListeners(Array.from(dependenciesMap), () => {
|
|
66
|
+
const themeName = this.services.runtime.themeName
|
|
68
67
|
const newComputedStylesheet = stylesheet(
|
|
69
|
-
this.services.runtime.getTheme(
|
|
70
|
-
this.services.runtime.
|
|
68
|
+
this.services.runtime.getTheme(themeName, this.services.state.CSSVars),
|
|
69
|
+
this.services.runtime.getMiniRuntime(themeName),
|
|
71
70
|
)
|
|
72
71
|
|
|
73
72
|
this.stylesheets.set(stylesheet, newComputedStylesheet)
|
package/src/web/runtime.ts
CHANGED
|
@@ -49,13 +49,8 @@ export class UnistylesRuntime {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
// App theme, like on native. ScopedTheme is read from React Context (useUnistyles) (#1295)
|
|
52
53
|
get themeName() {
|
|
53
|
-
const scopedTheme = this.services.shadowRegistry.getScopedTheme()
|
|
54
|
-
|
|
55
|
-
if (scopedTheme) {
|
|
56
|
-
return scopedTheme
|
|
57
|
-
}
|
|
58
|
-
|
|
59
54
|
if (this.services.state.hasAdaptiveThemes) {
|
|
60
55
|
return schemeToTheme(this.colorScheme) as AppThemeName
|
|
61
56
|
}
|
|
@@ -150,9 +145,14 @@ export class UnistylesRuntime {
|
|
|
150
145
|
}
|
|
151
146
|
|
|
152
147
|
get miniRuntime(): UnistylesMiniRuntime {
|
|
148
|
+
return this.getMiniRuntime(this.themeName)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// StyleSheets get the name of the theme they are called with
|
|
152
|
+
getMiniRuntime = (themeName?: AppThemeName): UnistylesMiniRuntime => {
|
|
153
153
|
return {
|
|
154
154
|
colorScheme: this.colorScheme,
|
|
155
|
-
themeName
|
|
155
|
+
themeName,
|
|
156
156
|
contentSizeCategory: this.contentSizeCategory,
|
|
157
157
|
breakpoint: this.breakpoint,
|
|
158
158
|
isLandscape: this.orientation === Orientation.Landscape,
|
|
@@ -6,7 +6,7 @@ import type { StyleSheet, StyleSheetWithSuperPowers, UnistylesValues } from '../
|
|
|
6
6
|
import type { UnistylesRuntime } from '../runtime'
|
|
7
7
|
|
|
8
8
|
import { ColorScheme, Orientation } from '../../specs/types'
|
|
9
|
-
import { isDefined, isUnistylesMq, parseMq } from '../../utils'
|
|
9
|
+
import { isAnimatedStyleHandle, isDefined, isUnistylesMq, parseMq } from '../../utils'
|
|
10
10
|
import * as unistyles from '../services'
|
|
11
11
|
import { UNI_GENERATED_KEYS, type UniGeneratedKey, type UniGeneratedStyle } from '../types'
|
|
12
12
|
import { hyphenate, keyInObject, reduceObject } from './common'
|
|
@@ -142,9 +142,7 @@ export const checkForAnimated = (value: any): boolean => {
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
if (typeof value === 'object' && value !== null) {
|
|
145
|
-
|
|
146
|
-
// styleUpdaterContainer was added in Reanimated 4.1, so check only the keys every version has
|
|
147
|
-
if ('viewDescriptors' in value && 'initial' in value) {
|
|
145
|
+
if (isAnimatedStyleHandle(value)) {
|
|
148
146
|
return true
|
|
149
147
|
}
|
|
150
148
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["web/convert/module.d.ts"],"mappings":"","ignoreList":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["web/convert/module.d.ts"],"mappings":"","ignoreList":[]}
|