react-native-unistyles 2.0.0-alpha.1 → 2.0.0-alpha.3

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.
Files changed (193) hide show
  1. package/README.md +4 -4
  2. package/ios/UnistylesModule.h +12 -0
  3. package/ios/UnistylesModule.mm +163 -0
  4. package/ios/UnistylesRuntime.h +48 -0
  5. package/ios/UnistylesRuntime.mm +228 -0
  6. package/lib/commonjs/UnistyleRegistry.js +34 -0
  7. package/lib/commonjs/UnistyleRegistry.js.map +1 -0
  8. package/lib/commonjs/Unistyles.js +36 -0
  9. package/lib/commonjs/Unistyles.js.map +1 -0
  10. package/lib/commonjs/UnistylesEngine.js +22 -0
  11. package/lib/commonjs/UnistylesEngine.js.map +1 -0
  12. package/lib/commonjs/UnistylesModule.js +9 -0
  13. package/lib/commonjs/UnistylesModule.js.map +1 -0
  14. package/lib/commonjs/UnistylesRuntime.js +63 -0
  15. package/lib/commonjs/UnistylesRuntime.js.map +1 -0
  16. package/lib/commonjs/createStyleSheet.js +14 -0
  17. package/lib/commonjs/createStyleSheet.js.map +1 -0
  18. package/lib/commonjs/global.js +2 -0
  19. package/lib/commonjs/global.js.map +1 -0
  20. package/lib/commonjs/hooks/useDimensions.web.js +3 -2
  21. package/lib/commonjs/hooks/useDimensions.web.js.map +1 -1
  22. package/lib/commonjs/index.js +33 -6
  23. package/lib/commonjs/index.js.map +1 -1
  24. package/lib/commonjs/types/cxx.js +23 -0
  25. package/lib/commonjs/types/cxx.js.map +1 -0
  26. package/lib/commonjs/types/index.js +26 -0
  27. package/lib/commonjs/types/index.js.map +1 -1
  28. package/lib/commonjs/types/normalizer.js +6 -0
  29. package/lib/commonjs/types/normalizer.js.map +1 -0
  30. package/lib/commonjs/useInitialTheme.js +13 -0
  31. package/lib/commonjs/useInitialTheme.js.map +1 -0
  32. package/lib/commonjs/useStyles.js +48 -0
  33. package/lib/commonjs/useStyles.js.map +1 -0
  34. package/lib/commonjs/useUnistyles.js +57 -0
  35. package/lib/commonjs/useUnistyles.js.map +1 -0
  36. package/lib/commonjs/utils/breakpoints.js +4 -2
  37. package/lib/commonjs/utils/breakpoints.js.map +1 -1
  38. package/lib/commonjs/utils/common.js +3 -3
  39. package/lib/commonjs/utils/common.js.map +1 -1
  40. package/lib/commonjs/utils/index.js +34 -0
  41. package/lib/commonjs/utils/index.js.map +1 -1
  42. package/lib/commonjs/utils/module.d.js +2 -0
  43. package/lib/commonjs/utils/module.d.js.map +1 -0
  44. package/lib/commonjs/utils/normalizeStyles.web.js +13 -13
  45. package/lib/commonjs/utils/normalizeStyles.web.js.map +1 -1
  46. package/lib/commonjs/utils/normalizer.js +89 -0
  47. package/lib/commonjs/utils/normalizer.js.map +1 -0
  48. package/lib/commonjs/utils/styles.js +7 -7
  49. package/lib/commonjs/utils/styles.js.map +1 -1
  50. package/lib/module/UnistyleRegistry.js +27 -0
  51. package/lib/module/UnistyleRegistry.js.map +1 -0
  52. package/lib/module/Unistyles.js +30 -0
  53. package/lib/module/Unistyles.js.map +1 -0
  54. package/lib/module/UnistylesEngine.js +15 -0
  55. package/lib/module/UnistylesEngine.js.map +1 -0
  56. package/lib/module/UnistylesModule.js +3 -0
  57. package/lib/module/UnistylesModule.js.map +1 -0
  58. package/lib/module/UnistylesRuntime.js +56 -0
  59. package/lib/module/UnistylesRuntime.js.map +1 -0
  60. package/lib/module/createStyleSheet.js +7 -0
  61. package/lib/module/createStyleSheet.js.map +1 -0
  62. package/lib/module/global.js +2 -0
  63. package/lib/module/global.js.map +1 -0
  64. package/lib/module/hooks/useDimensions.web.js +3 -2
  65. package/lib/module/hooks/useDimensions.web.js.map +1 -1
  66. package/lib/module/index.js +18 -2
  67. package/lib/module/index.js.map +1 -1
  68. package/lib/module/types/cxx.js +17 -0
  69. package/lib/module/types/cxx.js.map +1 -0
  70. package/lib/module/types/index.js +2 -1
  71. package/lib/module/types/index.js.map +1 -1
  72. package/lib/module/types/normalizer.js +2 -0
  73. package/lib/module/types/normalizer.js.map +1 -0
  74. package/lib/module/useInitialTheme.js +6 -0
  75. package/lib/module/useInitialTheme.js.map +1 -0
  76. package/lib/module/useStyles.js +42 -0
  77. package/lib/module/useStyles.js.map +1 -0
  78. package/lib/module/useUnistyles.js +50 -0
  79. package/lib/module/useUnistyles.js.map +1 -0
  80. package/lib/module/utils/breakpoints.js +4 -3
  81. package/lib/module/utils/breakpoints.js.map +1 -1
  82. package/lib/module/utils/common.js +2 -1
  83. package/lib/module/utils/common.js.map +1 -1
  84. package/lib/module/utils/index.js +2 -0
  85. package/lib/module/utils/index.js.map +1 -1
  86. package/lib/module/utils/module.d.js +2 -0
  87. package/lib/module/utils/module.d.js.map +1 -0
  88. package/lib/module/utils/normalizeStyles.web.js +13 -13
  89. package/lib/module/utils/normalizeStyles.web.js.map +1 -1
  90. package/lib/module/utils/normalizer.js +79 -0
  91. package/lib/module/utils/normalizer.js.map +1 -0
  92. package/lib/module/utils/styles.js +7 -8
  93. package/lib/module/utils/styles.js.map +1 -1
  94. package/lib/typescript/examples/expo/src/App.d.ts +3 -0
  95. package/lib/typescript/examples/expo/src/App.d.ts.map +1 -0
  96. package/lib/typescript/examples/expo/src/examples/Cxx.d.ts +3 -0
  97. package/lib/typescript/examples/expo/src/examples/Cxx.d.ts.map +1 -0
  98. package/lib/typescript/examples/expo/src/examples/index.d.ts +2 -0
  99. package/lib/typescript/examples/expo/src/examples/index.d.ts.map +1 -0
  100. package/lib/typescript/examples/expo/src/index.d.ts +2 -0
  101. package/lib/typescript/examples/expo/src/index.d.ts.map +1 -0
  102. package/lib/typescript/examples/expo/src/styles/breakpoints.d.ts +8 -0
  103. package/lib/typescript/examples/expo/src/styles/breakpoints.d.ts.map +1 -0
  104. package/lib/typescript/examples/expo/src/styles/index.d.ts +16 -0
  105. package/lib/typescript/examples/expo/src/styles/index.d.ts.map +1 -0
  106. package/lib/typescript/examples/expo/src/styles/theme.d.ts +40 -0
  107. package/lib/typescript/examples/expo/src/styles/theme.d.ts.map +1 -0
  108. package/lib/typescript/src/UnistyleRegistry.d.ts +14 -0
  109. package/lib/typescript/src/UnistyleRegistry.d.ts.map +1 -0
  110. package/lib/typescript/src/Unistyles.d.ts +16 -0
  111. package/lib/typescript/src/Unistyles.d.ts.map +1 -0
  112. package/lib/typescript/src/UnistylesEngine.d.ts +8 -0
  113. package/lib/typescript/src/UnistylesEngine.d.ts.map +1 -0
  114. package/lib/typescript/src/UnistylesModule.d.ts +6 -0
  115. package/lib/typescript/src/UnistylesModule.d.ts.map +1 -0
  116. package/lib/typescript/src/UnistylesRuntime.d.ts +60 -0
  117. package/lib/typescript/src/UnistylesRuntime.d.ts.map +1 -0
  118. package/lib/typescript/src/createStyleSheet.d.ts +6 -0
  119. package/lib/typescript/src/createStyleSheet.d.ts.map +1 -0
  120. package/lib/typescript/src/global.d.ts +5 -0
  121. package/lib/typescript/src/global.d.ts.map +1 -0
  122. package/lib/typescript/src/hooks/useDimensions.web.d.ts.map +1 -1
  123. package/lib/typescript/src/index.d.ts +14 -2
  124. package/lib/typescript/src/index.d.ts.map +1 -1
  125. package/lib/typescript/src/types/breakpoints.d.ts +6 -7
  126. package/lib/typescript/src/types/breakpoints.d.ts.map +1 -1
  127. package/lib/typescript/src/types/core.d.ts +4 -4
  128. package/lib/typescript/src/types/core.d.ts.map +1 -1
  129. package/lib/typescript/src/types/cxx.d.ts +53 -0
  130. package/lib/typescript/src/types/cxx.d.ts.map +1 -0
  131. package/lib/typescript/src/types/index.d.ts +4 -1
  132. package/lib/typescript/src/types/index.d.ts.map +1 -1
  133. package/lib/typescript/src/types/normalizer.d.ts +20 -0
  134. package/lib/typescript/src/types/normalizer.d.ts.map +1 -0
  135. package/lib/typescript/src/useInitialTheme.d.ts +3 -0
  136. package/lib/typescript/src/useInitialTheme.d.ts.map +1 -0
  137. package/lib/typescript/src/useStyles.d.ts +46 -0
  138. package/lib/typescript/src/useStyles.d.ts.map +1 -0
  139. package/lib/typescript/src/useUnistyles.d.ts +45 -0
  140. package/lib/typescript/src/useUnistyles.d.ts.map +1 -0
  141. package/lib/typescript/src/utils/breakpoints.d.ts +5 -4
  142. package/lib/typescript/src/utils/breakpoints.d.ts.map +1 -1
  143. package/lib/typescript/src/utils/common.d.ts +2 -1
  144. package/lib/typescript/src/utils/common.d.ts.map +1 -1
  145. package/lib/typescript/src/utils/index.d.ts +2 -0
  146. package/lib/typescript/src/utils/index.d.ts.map +1 -1
  147. package/lib/typescript/src/utils/normalizeStyles.web.d.ts +4 -1
  148. package/lib/typescript/src/utils/normalizeStyles.web.d.ts.map +1 -1
  149. package/lib/typescript/src/utils/normalizer.d.ts +11 -0
  150. package/lib/typescript/src/utils/normalizer.d.ts.map +1 -0
  151. package/lib/typescript/src/utils/styles.d.ts +4 -3
  152. package/lib/typescript/src/utils/styles.d.ts.map +1 -1
  153. package/package.json +13 -3
  154. package/react-native-unistyles.podspec +21 -0
  155. package/src/UnistyleRegistry.ts +35 -0
  156. package/src/Unistyles.ts +41 -0
  157. package/src/UnistylesEngine.ts +15 -0
  158. package/src/UnistylesModule.ts +7 -0
  159. package/src/UnistylesRuntime.ts +69 -0
  160. package/src/createStyleSheet.ts +12 -0
  161. package/src/global.ts +2 -0
  162. package/src/hooks/useDimensions.web.ts +3 -2
  163. package/src/index.ts +30 -2
  164. package/src/types/breakpoints.ts +9 -11
  165. package/src/types/core.ts +6 -6
  166. package/src/types/cxx.ts +65 -0
  167. package/src/types/index.ts +4 -3
  168. package/src/types/normalizer.ts +29 -0
  169. package/src/useInitialTheme.ts +7 -0
  170. package/src/useStyles.ts +49 -0
  171. package/src/useUnistyles.ts +66 -0
  172. package/src/utils/breakpoints.ts +16 -14
  173. package/src/utils/common.ts +2 -1
  174. package/src/utils/index.ts +2 -0
  175. package/src/utils/module.d.ts +3 -0
  176. package/src/utils/normalizeStyles.web.ts +21 -42
  177. package/src/utils/normalizer.ts +99 -0
  178. package/src/utils/styles.ts +17 -19
  179. package/lib/commonjs/UnistylesTheme.js +0 -21
  180. package/lib/commonjs/UnistylesTheme.js.map +0 -1
  181. package/lib/commonjs/createUnistyles.js +0 -57
  182. package/lib/commonjs/createUnistyles.js.map +0 -1
  183. package/lib/module/UnistylesTheme.js +0 -12
  184. package/lib/module/UnistylesTheme.js.map +0 -1
  185. package/lib/module/createUnistyles.js +0 -50
  186. package/lib/module/createUnistyles.js.map +0 -1
  187. package/lib/typescript/src/UnistylesTheme.d.ts +0 -9
  188. package/lib/typescript/src/UnistylesTheme.d.ts.map +0 -1
  189. package/lib/typescript/src/createUnistyles.d.ts +0 -10
  190. package/lib/typescript/src/createUnistyles.d.ts.map +0 -1
  191. package/src/UnistylesTheme.tsx +0 -17
  192. package/src/__tests__/createUnistyles.spec.tsx +0 -192
  193. package/src/createUnistyles.ts +0 -70
package/src/index.ts CHANGED
@@ -1,2 +1,30 @@
1
- export { UnistylesTheme } from './UnistylesTheme'
2
- export { createUnistyles } from './createUnistyles'
1
+ import { unistyles } from './Unistyles'
2
+ import type { UnistylesThemes, UnistylesBreakpoints } from './global'
3
+ import { ScreenOrientation } from './types'
4
+
5
+ export { useInitialTheme } from './useInitialTheme'
6
+
7
+ export { useStyles } from './useStyles'
8
+ export { createStyleSheet } from './createStyleSheet'
9
+
10
+ const { addThemes, addBreakpoints, addConfig } = unistyles.registry
11
+ const UnistylesRuntime = unistyles.runtime
12
+ const UnistylesRegistry = {
13
+ addThemes,
14
+ addBreakpoints,
15
+ addConfig
16
+ }
17
+
18
+ export {
19
+ UnistylesRuntime,
20
+ UnistylesRegistry
21
+ }
22
+
23
+ export {
24
+ ScreenOrientation
25
+ }
26
+
27
+ export type {
28
+ UnistylesThemes,
29
+ UnistylesBreakpoints
30
+ }
@@ -1,8 +1,6 @@
1
+ import type { UnistylesBreakpoints } from '../global'
1
2
  import type { MediaQueries } from './mediaQueries'
2
3
 
3
- export type Breakpoints = Record<string, number>
4
- export type SortedBreakpointEntries<B extends Breakpoints> = [[keyof B & string, number]]
5
-
6
4
  export type ScreenSize = {
7
5
  width: number,
8
6
  height: number
@@ -12,22 +10,22 @@ export type CreateStylesFactory<ST, Theme> = (theme: Theme) => ST
12
10
 
13
11
  type WithEmptyObject<V> = keyof V extends never ? {} : V
14
12
 
15
- export type ExtractBreakpoints<T, B extends Breakpoints> = T extends Partial<Record<keyof B & string, infer V>>
13
+ export type ExtractBreakpoints<T> = T extends Partial<Record<keyof UnistylesBreakpoints & string, infer V>>
16
14
  ? WithEmptyObject<V>
17
15
  : T extends (...args: infer A) => infer R
18
- ? (...args: A) => ExtractBreakpoints<R, B>
16
+ ? (...args: A) => ExtractBreakpoints<R>
19
17
  : {
20
18
  [K in keyof T]: T[K] extends (...args: infer A) => infer R
21
- ? (...args: A) => ExtractBreakpoints<R, B>
19
+ ? (...args: A) => ExtractBreakpoints<R>
22
20
  : T[K] extends object
23
- ? ExtractBreakpoints<T[K], B>
21
+ ? ExtractBreakpoints<T[K]>
24
22
  : T[K]
25
23
  }
26
24
 
27
- export type RemoveKeysWithPrefix<T, B extends Breakpoints> = T extends (...args: Array<any>) => infer R
28
- ? (...args: Parameters<T>) => RemoveKeysWithPrefix<R, B>
25
+ export type RemoveKeysWithPrefix<T> = T extends (...args: Array<any>) => infer R
26
+ ? (...args: Parameters<T>) => RemoveKeysWithPrefix<R>
29
27
  : T extends object
30
28
  ? T extends Record<string, infer _V>
31
- ? { [K in keyof T as K extends MediaQueries ? keyof B & string : K]: RemoveKeysWithPrefix<T[K], B> }
32
- : { [K in keyof T]: RemoveKeysWithPrefix<T[K], B> }
29
+ ? { [K in keyof T as K extends MediaQueries ? keyof UnistylesBreakpoints & string : K]: RemoveKeysWithPrefix<T[K]> }
30
+ : { [K in keyof T]: RemoveKeysWithPrefix<T[K]> }
33
31
  : T
package/src/types/core.ts CHANGED
@@ -14,8 +14,8 @@ import type {
14
14
  TranslateYTransform
15
15
  } from 'react-native/Libraries/StyleSheet/StyleSheetTypes'
16
16
  import type { ImageStyle, TextStyle, ViewStyle } from 'react-native'
17
- import type { Breakpoints } from './breakpoints'
18
17
  import type { MediaQueries } from './mediaQueries'
18
+ import type { UnistylesBreakpoints } from '../global'
19
19
 
20
20
  type ShadowOffset = {
21
21
  width: number,
@@ -60,14 +60,14 @@ type UnistyleView<B> = DeepUniStyle<Omit<ViewStyle, NestedTypes>, B>
60
60
  type UnistyleText<B> = DeepUniStyle<Omit<TextStyle, NestedTypes>, B>
61
61
  type UnistyleImage<B> = DeepUniStyle<Omit<ImageStyle, NestedTypes>, B>
62
62
 
63
- export type StaticStyles<B extends Breakpoints> =
63
+ export type StaticStyles<B> =
64
64
  | UnistyleView<B>
65
65
  | UnistyleText<B>
66
66
  | UnistyleImage<B>
67
67
  & UnistyleNested<B>
68
68
 
69
- export type CustomNamedStyles<T, B extends Breakpoints> = {
70
- [K in keyof T]: T[K] extends (...args: infer A) => StaticStyles<B>
71
- ? (...args: A) => StaticStyles<B>
72
- : StaticStyles<B>
69
+ export type CustomNamedStyles<T> = {
70
+ [K in keyof T]: T[K] extends (...args: infer A) => StaticStyles<UnistylesBreakpoints>
71
+ ? (...args: A) => StaticStyles<UnistylesBreakpoints>
72
+ : StaticStyles<UnistylesBreakpoints>
73
73
  }
@@ -0,0 +1,65 @@
1
+ import type { UnistylesThemes, UnistylesBreakpoints } from '../global'
2
+
3
+ export type Nullable<T> = T | null
4
+ export type ColorSchemeName = 'light' | 'dark' | undefined
5
+
6
+ export type UnistylesConfig = {
7
+ adaptiveThemes?: boolean
8
+ }
9
+
10
+ export enum ScreenOrientation {
11
+ Portrait = 1,
12
+ Landscape = 2
13
+ }
14
+
15
+ export type UnistylesBridge = {
16
+ // getters
17
+ screenWidth: number,
18
+ screenHeight: number,
19
+ hasAdaptiveThemes: boolean,
20
+ theme: keyof UnistylesThemes,
21
+ breakpoint: keyof UnistylesBreakpoints,
22
+ colorScheme: ColorSchemeName,
23
+ sortedBreakpointPairs: Array<[keyof UnistylesBreakpoints, UnistylesBreakpoints[keyof UnistylesBreakpoints]]>,
24
+
25
+ // setters
26
+ themes: Array<keyof UnistylesThemes>,
27
+ useBreakpoints(breakpoints: UnistylesBreakpoints): void,
28
+ useTheme(name: keyof UnistylesThemes): void,
29
+ useAdaptiveThemes(enable: boolean): void,
30
+ }
31
+
32
+ export enum CxxUnistylesEventTypes {
33
+ Theme = 'theme',
34
+ Size = 'size',
35
+ Breakpoint = 'breakpoint'
36
+ }
37
+
38
+ export type CxxUnistylesThemeEvent = {
39
+ type: CxxUnistylesEventTypes.Theme,
40
+ payload: {
41
+ themeName: keyof UnistylesThemes
42
+ }
43
+ }
44
+
45
+ export type CxxUnistylesSizeEvent = {
46
+ type: CxxUnistylesEventTypes.Size,
47
+ payload: {
48
+ width: number,
49
+ height: number
50
+ }
51
+ }
52
+
53
+ export type CxxUnistylesBreakpointEvent = {
54
+ type: CxxUnistylesEventTypes.Breakpoint,
55
+ payload: {
56
+ breakpoint: keyof UnistylesBreakpoints
57
+ }
58
+ }
59
+
60
+ export type UnistylesEvents = CxxUnistylesThemeEvent | CxxUnistylesSizeEvent | CxxUnistylesBreakpointEvent
61
+
62
+ export enum UnistylesError {
63
+ RuntimeUnavailable = 'UNISTYLES_ERROR_RUNTIME_UNAVAILABLE',
64
+ ThemeNotFound = 'UNISTYLES_ERROR_THEME_NOT_FOUND'
65
+ }
@@ -1,9 +1,10 @@
1
+ export * from './normalizer'
2
+ export * from './cxx'
1
3
  export type { CustomNamedStyles } from './core'
4
+ export type { MediaQueries } from './mediaQueries'
2
5
  export type {
3
6
  ScreenSize,
4
- Breakpoints,
5
7
  CreateStylesFactory,
6
8
  ExtractBreakpoints,
7
- RemoveKeysWithPrefix,
8
- SortedBreakpointEntries
9
+ RemoveKeysWithPrefix
9
10
  } from './breakpoints'
@@ -0,0 +1,29 @@
1
+ import type { ShadowStyleIOS, TextStyle, TransformsStyle } from 'react-native'
2
+
3
+ type TransformArrayElement<T> = T extends Array<infer U> ? U : never
4
+ type BoxShadow = Required<ShadowStyleIOS>
5
+ type TextShadow = Required<Pick<TextStyle, 'textShadowColor' | 'textShadowOffset' | 'textShadowRadius'>>
6
+ type Transforms = Array<TransformArrayElement<TransformsStyle['transform']>>
7
+
8
+ type NormalizedBoxShadow = {
9
+ shadowColor: undefined,
10
+ shadowOffset: undefined,
11
+ shadowOpacity: undefined,
12
+ shadowRadius: undefined,
13
+ boxShadow?: string
14
+ }
15
+
16
+ type NormalizedTextShadow = {
17
+ textShadowColor: undefined
18
+ textShadowOffset: undefined
19
+ textShadowRadius: undefined,
20
+ textShadow?: string
21
+ }
22
+
23
+ export type {
24
+ BoxShadow,
25
+ TextShadow,
26
+ Transforms,
27
+ NormalizedBoxShadow,
28
+ NormalizedTextShadow
29
+ }
@@ -0,0 +1,7 @@
1
+ import { useRef } from 'react'
2
+ import { unistyles } from './Unistyles'
3
+ import type { UnistylesThemes } from './global'
4
+
5
+ export const useInitialTheme = (forName: keyof UnistylesThemes) => {
6
+ useRef(unistyles.runtime.setTheme(forName))
7
+ }
@@ -0,0 +1,49 @@
1
+ import { useMemo } from 'react'
2
+ import { StyleSheet } from 'react-native'
3
+ import { parseStyle, proxifyFunction } from './utils'
4
+ import type { CreateStylesFactory, CustomNamedStyles, ExtractBreakpoints, RemoveKeysWithPrefix } from './types'
5
+ import { useUnistyles } from './useUnistyles'
6
+ import type { UnistylesThemes } from './global'
7
+
8
+ // todo types
9
+ type T = UnistylesThemes[keyof UnistylesThemes]
10
+
11
+ export const useStyles = <ST extends CustomNamedStyles<ST>>(stylesheet?: ST | CreateStylesFactory<ST, T>) => {
12
+ const { theme, breakpoint, screenSize } = useUnistyles()
13
+
14
+ if (!stylesheet) {
15
+ return {
16
+ theme,
17
+ breakpoint,
18
+ styles: {} as ExtractBreakpoints<RemoveKeysWithPrefix<ST>>
19
+ }
20
+ }
21
+
22
+ const parsedStyles = useMemo(() => typeof stylesheet === 'function'
23
+ ? stylesheet(theme!)
24
+ : stylesheet, [theme, stylesheet])
25
+
26
+ const dynamicStyleSheet = useMemo(() => Object
27
+ .entries(parsedStyles)
28
+ .reduce((acc, [key, value]) => {
29
+ const style = value as CustomNamedStyles<ST>
30
+
31
+ if (typeof value === 'function') {
32
+ return {
33
+ ...acc,
34
+ [key]: proxifyFunction(value, breakpoint!, screenSize)
35
+ }
36
+ }
37
+
38
+ return StyleSheet.create({
39
+ ...acc,
40
+ [key]: parseStyle<ST>(style, breakpoint!, screenSize)
41
+ })
42
+ }, {} as ST), [breakpoint, screenSize, parsedStyles])
43
+
44
+ return {
45
+ theme,
46
+ breakpoint,
47
+ styles: dynamicStyleSheet as ExtractBreakpoints<RemoveKeysWithPrefix<ST>>
48
+ }
49
+ }
@@ -0,0 +1,66 @@
1
+ import { NativeEventEmitter, NativeModules } from 'react-native'
2
+ import { useEffect, useState } from 'react'
3
+ import type {
4
+ CxxUnistylesBreakpointEvent,
5
+ CxxUnistylesSizeEvent,
6
+ CxxUnistylesThemeEvent,
7
+ UnistylesEvents
8
+ } from './types'
9
+ import { CxxUnistylesEventTypes } from './types'
10
+ import { unistyles } from './Unistyles'
11
+
12
+ const unistylesEvents = new NativeEventEmitter(NativeModules.Unistyles)
13
+
14
+ export const useUnistyles = () => {
15
+ const [theme, setTheme] = useState(unistyles.runtime.getTheme(unistyles.runtime.themeName))
16
+ const [breakpoint, setBreakpoint] = useState(unistyles.runtime.breakpoint)
17
+ const [screenSize, setScreenSize] = useState({
18
+ width: 0,
19
+ height: 0
20
+ })
21
+
22
+ useEffect(() => {
23
+ const subscription = unistylesEvents.addListener(
24
+ 'onChange',
25
+ (event: UnistylesEvents) => {
26
+ switch (event.type) {
27
+ case CxxUnistylesEventTypes.Theme: {
28
+ const themeEvent = event as CxxUnistylesThemeEvent
29
+
30
+ setTheme(unistyles.runtime.getTheme(themeEvent.payload.themeName))
31
+
32
+ return
33
+ }
34
+ // this event is not available on mobile
35
+ case CxxUnistylesEventTypes.Size: {
36
+ const sizeEvent = event as CxxUnistylesSizeEvent
37
+
38
+ setScreenSize({
39
+ width: sizeEvent.payload.width,
40
+ height: sizeEvent.payload.height
41
+ })
42
+
43
+ return
44
+ }
45
+ case CxxUnistylesEventTypes.Breakpoint: {
46
+ const breakpointEvent = event as CxxUnistylesBreakpointEvent
47
+
48
+ setBreakpoint(breakpointEvent.payload.breakpoint)
49
+
50
+ return
51
+ }
52
+ default:
53
+ return
54
+ }
55
+ }
56
+ )
57
+
58
+ return subscription.remove
59
+ }, [])
60
+
61
+ return {
62
+ theme,
63
+ breakpoint,
64
+ screenSize
65
+ }
66
+ }
@@ -1,6 +1,8 @@
1
+ import { unistyles } from '../Unistyles'
1
2
  import { throwError } from './common'
2
- import type { Breakpoints, ScreenSize, SortedBreakpointEntries } from '../types'
3
+ import type { ScreenSize, MediaQueries } from '../types'
3
4
  import { getKeyForCustomMediaQuery, isMediaQuery } from './mediaQueries'
5
+ import type { UnistylesBreakpoints } from '../global'
4
6
 
5
7
  /**
6
8
  * Sorts the breakpoints object based on its numeric values in ascending order and validates them.
@@ -21,17 +23,17 @@ import { getKeyForCustomMediaQuery, isMediaQuery } from './mediaQueries'
21
23
  * const input = { md: 768, lg: 1024, sm: 0 }
22
24
  * sortAndValidateBreakpoints(input) // returns { sm: 0, md: 768, lg: 1024 }
23
25
  */
24
- export const sortAndValidateBreakpoints = <B extends Breakpoints>(breakpoints: B): B => {
26
+ export const sortAndValidateBreakpoints = (breakpoints: UnistylesBreakpoints): UnistylesBreakpoints => {
25
27
  const sortedPairs = Object
26
28
  .entries(breakpoints)
27
29
  .sort((breakpoint1, breakpoint2) => {
28
30
  const [, value1] = breakpoint1
29
31
  const [, value2] = breakpoint2
30
32
 
31
- return value1 - value2
33
+ return (value1 as number) - (value2 as number)
32
34
  })
33
35
 
34
- const sortedBreakpoints = Object.freeze(Object.fromEntries(sortedPairs)) as B
36
+ const sortedBreakpoints = Object.freeze(Object.fromEntries(sortedPairs)) as UnistylesBreakpoints
35
37
  const breakpointValues = Object.values(sortedBreakpoints)
36
38
  const [firstBreakpoint] = breakpointValues
37
39
 
@@ -61,7 +63,7 @@ export const sortAndValidateBreakpoints = <B extends Breakpoints>(breakpoints: B
61
63
  * const breakpoints = { sm: 0, md: 768, lg: 1024 }
62
64
  * getBreakpointFromScreenWidth(800, breakpoints) // returns 'md'
63
65
  */
64
- export const getBreakpointFromScreenWidth = <B extends Breakpoints>(width: number, breakpointEntries: SortedBreakpointEntries<B>): keyof B & string => {
66
+ export const getBreakpointFromScreenWidth = (width: number, breakpointEntries: Array<[keyof UnistylesBreakpoints, UnistylesBreakpoints[keyof UnistylesBreakpoints]]>): keyof UnistylesBreakpoints & string => {
65
67
  const [key] = breakpointEntries
66
68
  .find(([, value], index, otherBreakpoints) => {
67
69
  const minVal = value
@@ -72,7 +74,7 @@ export const getBreakpointFromScreenWidth = <B extends Breakpoints>(width: numbe
72
74
  }
73
75
 
74
76
  return width >= minVal && width < maxVal
75
- }) as [keyof B & string, number]
77
+ }) as [keyof UnistylesBreakpoints & string, number]
76
78
 
77
79
  return key
78
80
  }
@@ -101,24 +103,23 @@ export const getBreakpointFromScreenWidth = <B extends Breakpoints>(width: numbe
101
103
  *
102
104
  * getValueForBreakpoint(values, 'sm', screenSize, breakpoints); // 'value1'
103
105
  */
104
- export const getValueForBreakpoint = <B extends Breakpoints>(
105
- value: Record<keyof B & string, string | number | undefined>,
106
- breakpoint: keyof B & string,
107
- screenSize: ScreenSize,
108
- breakpointPairs: SortedBreakpointEntries<B>
106
+ export const getValueForBreakpoint = (
107
+ value: Record<keyof UnistylesBreakpoints | MediaQueries, string | number | undefined>,
108
+ breakpoint: keyof UnistylesBreakpoints,
109
+ screenSize: ScreenSize
109
110
  ): string | number | undefined => {
110
111
  // the highest priority is for custom media queries
111
112
  const customMediaQueries = Object
112
113
  .entries(value)
113
114
  .filter(([key]) => isMediaQuery(key))
114
- const customMediaQueryKey = getKeyForCustomMediaQuery(customMediaQueries, screenSize)
115
+ const customMediaQueryKey = getKeyForCustomMediaQuery(customMediaQueries, screenSize) as keyof typeof value
115
116
 
116
117
  if (customMediaQueryKey && customMediaQueryKey in value) {
117
118
  return value[customMediaQueryKey]
118
119
  }
119
120
 
120
121
  // if no custom media query, or didn't match, proceed with defined breakpoints
121
- const unifiedKey = breakpoint.toLowerCase()
122
+ const unifiedKey = breakpoint?.toLowerCase() as keyof typeof value
122
123
  const directBreakpoint = value[unifiedKey]
123
124
 
124
125
  // if there is a direct key like 'sm' or 'md', or value for this key exists but its undefined
@@ -127,6 +128,7 @@ export const getValueForBreakpoint = <B extends Breakpoints>(
127
128
  }
128
129
 
129
130
  // there is no direct hit for breakpoint nor media-query, so let's simulate CSS cascading
131
+ const breakpointPairs = unistyles.runtime.sortedBreakpoints
130
132
  const currentBreakpoint = breakpointPairs
131
133
  .findIndex(([key]) => key === unifiedKey)
132
134
 
@@ -135,6 +137,6 @@ export const getValueForBreakpoint = <B extends Breakpoints>(
135
137
  .map(([key]) => key)
136
138
 
137
139
  return breakpointPairs.length > 0
138
- ? value[availableBreakpoints[availableBreakpoints.length - 1] as keyof B & string]
140
+ ? value[availableBreakpoints[availableBreakpoints.length - 1] as keyof UnistylesBreakpoints & string]
139
141
  : undefined
140
142
  }
@@ -8,4 +8,5 @@ export const warn = (message: string) => {
8
8
  console.warn(`🦄 [react-native-unistyles]: ${message}`)
9
9
  }
10
10
 
11
- export const isWeb = () => Platform.OS === 'web'
11
+ export const isWeb = Platform.OS === 'web'
12
+ export const isServer = typeof window === 'undefined'
@@ -1,6 +1,8 @@
1
1
  export { normalizeStyles } from './normalizeStyles'
2
+ export * from './normalizer'
2
3
  export { getBreakpointFromScreenWidth, sortAndValidateBreakpoints, getValueForBreakpoint } from './breakpoints'
3
4
  export { proxifyFunction, parseStyle } from './styles'
5
+ export { isServer } from './common'
4
6
  export {
5
7
  extractValues,
6
8
  getKeyForCustomMediaQuery,
@@ -0,0 +1,3 @@
1
+ declare module '@react-native/normalize-colors' {
2
+ export default function normalizeColor(color: string): number | null
3
+ }
@@ -1,29 +1,8 @@
1
1
  import { warn } from './common'
2
+ import { preprocessor } from './normalizer'
3
+ import type { NormalizedBoxShadow, NormalizedTextShadow, BoxShadow, TextShadow, Transforms } from '../types'
2
4
 
3
- const preprocessor: Preprocessor = require('react-native-web/src/exports/StyleSheet/preprocess.js')
4
-
5
- type Preprocessor = {
6
- createTextShadowValue<T>(styles: any): T,
7
- createBoxShadowValue<T>(styles: any): T,
8
- createTransformValue<T>(transforms: any): T,
9
- }
10
-
11
- type NormalizedBoxShadow = {
12
- shadowColor: undefined,
13
- shadowOffset: undefined,
14
- shadowOpacity: undefined,
15
- shadowRadius: undefined,
16
- boxShadow?: string
17
- }
18
-
19
- type NormalizedTextShadow = {
20
- textShadowColor: undefined
21
- textShadowOffset: undefined
22
- textShadowRadius: undefined,
23
- textShadow?: string
24
- }
25
-
26
- const normalizeBoxShadow = <T extends {}>(styles: T): NormalizedBoxShadow => {
5
+ const normalizeBoxShadow = <T extends BoxShadow>(style: T): NormalizedBoxShadow => {
27
6
  const requiredBoxShadowProperties = [
28
7
  'shadowColor',
29
8
  'shadowOffset',
@@ -31,7 +10,7 @@ const normalizeBoxShadow = <T extends {}>(styles: T): NormalizedBoxShadow => {
31
10
  'shadowRadius'
32
11
  ]
33
12
 
34
- if (!requiredBoxShadowProperties.every(prop => prop in styles)) {
13
+ if (!requiredBoxShadowProperties.every(prop => prop in style)) {
35
14
  warn(`can't apply box shadow as you miss at least one of these properties: ${requiredBoxShadowProperties.join(', ')}`)
36
15
 
37
16
  return {
@@ -43,7 +22,7 @@ const normalizeBoxShadow = <T extends {}>(styles: T): NormalizedBoxShadow => {
43
22
  }
44
23
 
45
24
  return {
46
- boxShadow: preprocessor.createBoxShadowValue(styles),
25
+ boxShadow: preprocessor.createBoxShadowValue(style),
47
26
  shadowColor: undefined,
48
27
  shadowOffset: undefined,
49
28
  shadowOpacity: undefined,
@@ -51,14 +30,14 @@ const normalizeBoxShadow = <T extends {}>(styles: T): NormalizedBoxShadow => {
51
30
  }
52
31
  }
53
32
 
54
- const normalizeTextShadow = <T extends {}>(styles: T): NormalizedTextShadow => {
33
+ const normalizeTextShadow = <T extends TextShadow>(style: T): NormalizedTextShadow => {
55
34
  const requiredTextShadowProperties = [
56
35
  'textShadowColor',
57
36
  'textShadowOffset',
58
37
  'textShadowRadius'
59
38
  ]
60
39
 
61
- if (!requiredTextShadowProperties.every(prop => prop in styles)) {
40
+ if (!requiredTextShadowProperties.every(prop => prop in style)) {
62
41
  warn(`can't apply text shadow as you miss at least one of these properties: ${requiredTextShadowProperties.join(', ')}`)
63
42
 
64
43
  return {
@@ -69,33 +48,33 @@ const normalizeTextShadow = <T extends {}>(styles: T): NormalizedTextShadow => {
69
48
  }
70
49
 
71
50
  return {
72
- textShadow: preprocessor.createTextShadowValue(styles),
51
+ textShadow: preprocessor.createTextShadowValue(style),
73
52
  textShadowColor: undefined,
74
53
  textShadowOffset: undefined,
75
54
  textShadowRadius: undefined
76
55
  }
77
56
  }
78
57
 
79
- export const normalizeStyles = <T extends {}>(styles: T): T => {
80
- const normalizedTransform = ('transform' in styles && Array.isArray(styles.transform))
81
- ? { transform: preprocessor.createTransformValue(styles.transform) }
58
+ export const normalizeStyles = <T extends BoxShadow | TextShadow | { transform: Transforms }>(style: T): T => {
59
+ const normalizedTransform = ('transform' in style && Array.isArray(style.transform))
60
+ ? { transform: preprocessor.createTransformValue(style.transform) }
82
61
  : {}
83
62
 
84
63
  const normalizedBoxShadow = (
85
- 'shadowColor' in styles ||
86
- 'shadowOffset' in styles ||
87
- 'shadowOpacity' in styles ||
88
- 'shadowRadius' in styles
89
- ) ? normalizeBoxShadow(styles) : {}
64
+ 'shadowColor' in style ||
65
+ 'shadowOffset' in style ||
66
+ 'shadowOpacity' in style ||
67
+ 'shadowRadius' in style
68
+ ) ? normalizeBoxShadow(style as BoxShadow) : {}
90
69
 
91
70
  const normalizedTextShadow = (
92
- 'textShadowColor' in styles ||
93
- 'textShadowOffset' in styles ||
94
- 'textShadowRadius' in styles
95
- ) ? normalizeTextShadow(styles) : {}
71
+ 'textShadowColor' in style ||
72
+ 'textShadowOffset' in style ||
73
+ 'textShadowRadius' in style
74
+ ) ? normalizeTextShadow(style as TextShadow) : {}
96
75
 
97
76
  return {
98
- ...styles,
77
+ ...style,
99
78
  ...normalizedTransform,
100
79
  ...normalizedBoxShadow,
101
80
  ...normalizedTextShadow
@@ -0,0 +1,99 @@
1
+ // based on react-native-web normalizer
2
+ // https://github.com/necolas/react-native-web
3
+ import normalizeColors from '@react-native/normalize-colors'
4
+ import type { TextShadow, Transforms, BoxShadow } from '../types'
5
+
6
+ type Preprocessor = {
7
+ createTextShadowValue(style: TextShadow): string,
8
+ createBoxShadowValue(style: Required<BoxShadow>): string,
9
+ createTransformValue(transforms: Required<Transforms>): string,
10
+ }
11
+
12
+ export const normalizeColor = (color: string, opacity: number = 1) => {
13
+ // If the opacity is 1 there's no need to normalize the color
14
+ if (opacity === 1) {
15
+ return color
16
+ }
17
+
18
+ const integer = normalizeColors(color) as number | null
19
+
20
+ // If the colour is an unknown format, the return value is null
21
+ if (integer === null) {
22
+ return color
23
+ }
24
+
25
+ const hex = integer.toString(16).padStart(8, '0')
26
+
27
+ if (hex.length === 8) {
28
+ const [r = 0, g = 0, b = 0, a = 1] = hex
29
+ .split(/(?=(?:..)*$)/)
30
+ .map(x => parseInt(x, 16))
31
+ .filter(num => !isNaN(num))
32
+
33
+ return `rgba(${r},${g},${b},${((a as number) / 255) * opacity})`
34
+ }
35
+
36
+ return color
37
+ }
38
+
39
+ export const normalizeNumericValue = (value: number) => value ? `${value}px` : value
40
+ const normalizeTransform = (key: string, value: number | string) => {
41
+ if (key.includes('scale')) {
42
+ return value
43
+ }
44
+
45
+ if (typeof value === 'number') {
46
+ return normalizeNumericValue(value)
47
+ }
48
+
49
+ return value
50
+ }
51
+
52
+ const createTextShadowValue = (style: TextShadow) => {
53
+ // at this point every prop is present
54
+ const { textShadowColor, textShadowOffset, textShadowRadius } = style
55
+ const offsetX = normalizeNumericValue(textShadowOffset.width)
56
+ const offsetY = normalizeNumericValue(textShadowOffset.height)
57
+ const radius = normalizeNumericValue(textShadowRadius)
58
+ const color = normalizeColor(textShadowColor as string)
59
+
60
+ return `${offsetX} ${offsetY} ${radius} ${color}`
61
+ }
62
+
63
+ const createBoxShadowValue = (style: BoxShadow) => {
64
+ // at this point every prop is present
65
+ const { shadowColor, shadowOffset, shadowOpacity, shadowRadius } = style
66
+ const offsetX = normalizeNumericValue(shadowOffset.width)
67
+ const offsetY = normalizeNumericValue(shadowOffset.height)
68
+ const radius = normalizeNumericValue(shadowRadius)
69
+ const color = normalizeColor(shadowColor as string, shadowOpacity as number)
70
+
71
+ return `${offsetX} ${offsetY} ${radius} ${color}`
72
+ }
73
+
74
+ const createTransformValue = (transforms: Transforms) => transforms
75
+ .map(transform => {
76
+ const [key] = Object.keys(transform)
77
+
78
+ if (!key) {
79
+ return undefined
80
+ }
81
+
82
+ const value = transform[key as keyof typeof transform]
83
+
84
+ switch(key) {
85
+ case 'matrix':
86
+ case 'matrix3d':
87
+ return `${key}(${(value as Array<number>).join(',')})`
88
+ default:
89
+ return `${key}(${normalizeTransform(key, value)})`
90
+ }
91
+ })
92
+ .filter(Boolean)
93
+ .join(' ')
94
+
95
+ export const preprocessor: Preprocessor = {
96
+ createTextShadowValue,
97
+ createBoxShadowValue,
98
+ createTransformValue
99
+ }