react-native-unistyles 3.0.0-alpha.40 → 3.0.0-alpha.42

Sign up to get free protection for your applications and to get access to all the features.
Files changed (226) hide show
  1. package/README.md +7 -1
  2. package/android/CMakeLists.txt +3 -0
  3. package/android/build.gradle +10 -0
  4. package/android/src/main/java/com/unistyles/NativePlatform+android.kt +10 -1
  5. package/cxx/core/UnistyleData.h +3 -2
  6. package/cxx/core/UnistylesRegistry.cpp +15 -5
  7. package/cxx/core/UnistylesRegistry.h +2 -2
  8. package/cxx/hybridObjects/HybridShadowRegistry.cpp +5 -2
  9. package/cxx/parser/Parser.cpp +10 -4
  10. package/cxx/shadowTree/ShadowLeafUpdate.h +1 -0
  11. package/cxx/shadowTree/ShadowTreeManager.cpp +4 -0
  12. package/ios/Extensions.swift +3 -1
  13. package/ios/NativePlatform+ios.swift +13 -2
  14. package/ios/NativePlatformListener+ios.swift +0 -1
  15. package/lib/commonjs/components/Display.js +2 -2
  16. package/lib/commonjs/components/Display.js.map +1 -1
  17. package/lib/commonjs/components/Hide.js +2 -2
  18. package/lib/commonjs/components/Hide.js.map +1 -1
  19. package/lib/commonjs/components/Pressable.js +64 -0
  20. package/lib/commonjs/components/Pressable.js.map +1 -0
  21. package/lib/commonjs/components/Pressable.web.js +97 -0
  22. package/lib/commonjs/components/Pressable.web.js.map +1 -0
  23. package/lib/commonjs/components/index.js +7 -0
  24. package/lib/commonjs/components/index.js.map +1 -1
  25. package/lib/commonjs/core/getBoundArgs.js +18 -0
  26. package/lib/commonjs/core/getBoundArgs.js.map +1 -0
  27. package/lib/commonjs/core/getId.js +9 -0
  28. package/lib/commonjs/core/getId.js.map +1 -0
  29. package/lib/commonjs/core/index.js +14 -0
  30. package/lib/commonjs/core/index.js.map +1 -1
  31. package/lib/commonjs/hooks/index.js +13 -0
  32. package/lib/commonjs/hooks/index.js.map +1 -0
  33. package/lib/commonjs/hooks/useMedia.js.map +1 -0
  34. package/lib/commonjs/hooks/useMedia.web.js.map +1 -0
  35. package/lib/commonjs/index.js +8 -1
  36. package/lib/commonjs/index.js.map +1 -1
  37. package/lib/commonjs/mq.js +6 -6
  38. package/lib/commonjs/mq.js.map +1 -1
  39. package/lib/commonjs/specs/ShadowRegistry/index.js +3 -4
  40. package/lib/commonjs/specs/ShadowRegistry/index.js.map +1 -1
  41. package/lib/commonjs/specs/StyleSheet/index.js.map +1 -1
  42. package/lib/commonjs/specs/TurboUnistyles/NativeTurboUnistyles.js +1 -2
  43. package/lib/commonjs/specs/TurboUnistyles/NativeTurboUnistyles.js.map +1 -1
  44. package/lib/commonjs/specs/index.web.js +0 -7
  45. package/lib/commonjs/specs/index.web.js.map +1 -1
  46. package/lib/commonjs/utils.js +1 -1
  47. package/lib/commonjs/utils.js.map +1 -1
  48. package/lib/commonjs/web/convert/types.js.map +1 -1
  49. package/lib/commonjs/web/convert/utils.js +1 -1
  50. package/lib/commonjs/web/convert/utils.js.map +1 -1
  51. package/lib/commonjs/web/create.js +4 -1
  52. package/lib/commonjs/web/create.js.map +1 -1
  53. package/lib/commonjs/web/index.js +7 -5
  54. package/lib/commonjs/web/index.js.map +1 -1
  55. package/lib/commonjs/web/listener.js.map +1 -1
  56. package/lib/commonjs/web/runtime.js +7 -7
  57. package/lib/commonjs/web/runtime.js.map +1 -1
  58. package/lib/commonjs/web/shadowRegistry.js.map +1 -1
  59. package/lib/commonjs/web/state.js +23 -16
  60. package/lib/commonjs/web/state.js.map +1 -1
  61. package/lib/commonjs/web/utils/common.js +3 -3
  62. package/lib/commonjs/web/utils/common.js.map +1 -1
  63. package/lib/commonjs/web/utils/unistyle.js +2 -4
  64. package/lib/commonjs/web/utils/unistyle.js.map +1 -1
  65. package/lib/commonjs/web/variants/getVariants.js +1 -1
  66. package/lib/commonjs/web/variants/getVariants.js.map +1 -1
  67. package/lib/commonjs/web/variants/useVariants.js +1 -1
  68. package/lib/module/components/Display.js +1 -1
  69. package/lib/module/components/Display.js.map +1 -1
  70. package/lib/module/components/Hide.js +1 -1
  71. package/lib/module/components/Hide.js.map +1 -1
  72. package/lib/module/components/Pressable.js +58 -0
  73. package/lib/module/components/Pressable.js.map +1 -0
  74. package/lib/module/components/Pressable.web.js +91 -0
  75. package/lib/module/components/Pressable.web.js.map +1 -0
  76. package/lib/module/components/index.js +1 -0
  77. package/lib/module/components/index.js.map +1 -1
  78. package/lib/module/core/getBoundArgs.js +13 -0
  79. package/lib/module/core/getBoundArgs.js.map +1 -0
  80. package/lib/module/core/getId.js +4 -0
  81. package/lib/module/core/getId.js.map +1 -0
  82. package/lib/module/core/index.js +2 -0
  83. package/lib/module/core/index.js.map +1 -1
  84. package/lib/module/hooks/index.js +4 -0
  85. package/lib/module/hooks/index.js.map +1 -0
  86. package/lib/module/hooks/useMedia.js.map +1 -0
  87. package/lib/module/hooks/useMedia.web.js.map +1 -0
  88. package/lib/module/index.js +1 -1
  89. package/lib/module/index.js.map +1 -1
  90. package/lib/module/mq.js +6 -6
  91. package/lib/module/mq.js.map +1 -1
  92. package/lib/module/specs/ShadowRegistry/index.js +3 -4
  93. package/lib/module/specs/ShadowRegistry/index.js.map +1 -1
  94. package/lib/module/specs/StyleSheet/index.js.map +1 -1
  95. package/lib/module/specs/TurboUnistyles/NativeTurboUnistyles.js +1 -2
  96. package/lib/module/specs/TurboUnistyles/NativeTurboUnistyles.js.map +1 -1
  97. package/lib/module/specs/index.web.js +0 -1
  98. package/lib/module/specs/index.web.js.map +1 -1
  99. package/lib/module/utils.js +1 -1
  100. package/lib/module/utils.js.map +1 -1
  101. package/lib/module/web/convert/types.js.map +1 -1
  102. package/lib/module/web/convert/utils.js +1 -1
  103. package/lib/module/web/convert/utils.js.map +1 -1
  104. package/lib/module/web/create.js +5 -2
  105. package/lib/module/web/create.js.map +1 -1
  106. package/lib/module/web/index.js +7 -3
  107. package/lib/module/web/index.js.map +1 -1
  108. package/lib/module/web/listener.js.map +1 -1
  109. package/lib/module/web/runtime.js +8 -8
  110. package/lib/module/web/runtime.js.map +1 -1
  111. package/lib/module/web/shadowRegistry.js.map +1 -1
  112. package/lib/module/web/state.js +24 -17
  113. package/lib/module/web/state.js.map +1 -1
  114. package/lib/module/web/utils/common.js +1 -1
  115. package/lib/module/web/utils/common.js.map +1 -1
  116. package/lib/module/web/utils/unistyle.js +1 -2
  117. package/lib/module/web/utils/unistyle.js.map +1 -1
  118. package/lib/module/web/variants/getVariants.js +1 -1
  119. package/lib/module/web/variants/getVariants.js.map +1 -1
  120. package/lib/module/web/variants/useVariants.js +1 -1
  121. package/lib/typescript/src/components/Pressable.d.ts +7 -0
  122. package/lib/typescript/src/components/Pressable.d.ts.map +1 -0
  123. package/lib/typescript/src/components/Pressable.web.d.ts +13 -0
  124. package/lib/typescript/src/components/Pressable.web.d.ts.map +1 -0
  125. package/lib/typescript/src/components/index.d.ts +1 -0
  126. package/lib/typescript/src/components/index.d.ts.map +1 -1
  127. package/lib/typescript/src/core/getBoundArgs.d.ts +2 -0
  128. package/lib/typescript/src/core/getBoundArgs.d.ts.map +1 -0
  129. package/lib/typescript/src/core/getId.d.ts +2 -0
  130. package/lib/typescript/src/core/getId.d.ts.map +1 -0
  131. package/lib/typescript/src/core/index.d.ts +2 -0
  132. package/lib/typescript/src/core/index.d.ts.map +1 -1
  133. package/lib/typescript/src/hooks/index.d.ts +2 -0
  134. package/lib/typescript/src/hooks/index.d.ts.map +1 -0
  135. package/lib/typescript/src/hooks/useMedia.d.ts.map +1 -0
  136. package/lib/typescript/src/hooks/useMedia.web.d.ts.map +1 -0
  137. package/lib/typescript/src/index.d.ts +1 -1
  138. package/lib/typescript/src/index.d.ts.map +1 -1
  139. package/lib/typescript/src/specs/NativePlatform/NativePlatform.nitro.d.ts +1 -1
  140. package/lib/typescript/src/specs/NativePlatform/NativePlatform.nitro.d.ts.map +1 -1
  141. package/lib/typescript/src/specs/ShadowRegistry/index.d.ts +2 -2
  142. package/lib/typescript/src/specs/ShadowRegistry/index.d.ts.map +1 -1
  143. package/lib/typescript/src/specs/ShadowRegistry/types.d.ts +1 -0
  144. package/lib/typescript/src/specs/ShadowRegistry/types.d.ts.map +1 -1
  145. package/lib/typescript/src/specs/StyleSheet/UnistylesStyleSheet.nitro.d.ts +1 -1
  146. package/lib/typescript/src/specs/StyleSheet/UnistylesStyleSheet.nitro.d.ts.map +1 -1
  147. package/lib/typescript/src/specs/StyleSheet/index.d.ts +3 -2
  148. package/lib/typescript/src/specs/StyleSheet/index.d.ts.map +1 -1
  149. package/lib/typescript/src/specs/UnistylesRuntime/index.d.ts +1 -1
  150. package/lib/typescript/src/specs/UnistylesRuntime/index.d.ts.map +1 -1
  151. package/lib/typescript/src/specs/index.web.d.ts +0 -2
  152. package/lib/typescript/src/specs/index.web.d.ts.map +1 -1
  153. package/lib/typescript/src/types/common.d.ts +1 -0
  154. package/lib/typescript/src/types/common.d.ts.map +1 -1
  155. package/lib/typescript/src/types/index.d.ts +1 -1
  156. package/lib/typescript/src/types/index.d.ts.map +1 -1
  157. package/lib/typescript/src/web/convert/types.d.ts +1 -1
  158. package/lib/typescript/src/web/convert/types.d.ts.map +1 -1
  159. package/lib/typescript/src/web/create.d.ts +1 -1
  160. package/lib/typescript/src/web/create.d.ts.map +1 -1
  161. package/lib/typescript/src/web/index.d.ts +8 -2
  162. package/lib/typescript/src/web/index.d.ts.map +1 -1
  163. package/lib/typescript/src/web/listener.d.ts.map +1 -1
  164. package/lib/typescript/src/web/runtime.d.ts.map +1 -1
  165. package/lib/typescript/src/web/state.d.ts.map +1 -1
  166. package/lib/typescript/src/web/utils/common.d.ts +1 -1
  167. package/lib/typescript/src/web/utils/common.d.ts.map +1 -1
  168. package/lib/typescript/src/web/utils/unistyle.d.ts +0 -1
  169. package/lib/typescript/src/web/utils/unistyle.d.ts.map +1 -1
  170. package/nitrogen/generated/ios/Unistyles-Swift-Cxx-Umbrella.hpp +1 -1
  171. package/package.json +14 -18
  172. package/plugin/common.js +1 -4
  173. package/plugin/import.js +29 -3
  174. package/plugin/index.js +16 -6
  175. package/plugin/ref.js +4 -54
  176. package/plugin/style.js +116 -43
  177. package/src/components/Display.tsx +1 -1
  178. package/src/components/Hide.tsx +1 -1
  179. package/src/components/Pressable.tsx +72 -0
  180. package/src/components/Pressable.web.tsx +103 -0
  181. package/src/components/index.ts +1 -0
  182. package/src/core/getBoundArgs.ts +15 -0
  183. package/src/core/getId.ts +1 -0
  184. package/src/core/index.ts +2 -0
  185. package/src/hooks/index.ts +1 -0
  186. package/src/index.ts +1 -1
  187. package/src/mq.ts +6 -6
  188. package/src/specs/NativePlatform/NativePlatform.nitro.ts +1 -1
  189. package/src/specs/ShadowRegistry/index.ts +5 -6
  190. package/src/specs/ShadowRegistry/types.ts +2 -1
  191. package/src/specs/StyleSheet/UnistylesStyleSheet.nitro.ts +1 -1
  192. package/src/specs/StyleSheet/index.ts +3 -2
  193. package/src/specs/TurboUnistyles/NativeTurboUnistyles.ts +1 -2
  194. package/src/specs/UnistylesRuntime/UnistylesRuntime.nitro.ts +1 -1
  195. package/src/specs/UnistylesRuntime/index.ts +1 -1
  196. package/src/specs/index.web.ts +0 -4
  197. package/src/types/common.ts +1 -0
  198. package/src/types/index.ts +1 -1
  199. package/src/utils.ts +1 -1
  200. package/src/web/convert/types.ts +1 -1
  201. package/src/web/convert/utils.ts +2 -2
  202. package/src/web/create.ts +6 -2
  203. package/src/web/index.ts +7 -3
  204. package/src/web/listener.ts +2 -0
  205. package/src/web/registry.ts +1 -1
  206. package/src/web/runtime.ts +9 -9
  207. package/src/web/shadowRegistry.ts +2 -2
  208. package/src/web/state.ts +36 -17
  209. package/src/web/utils/common.ts +1 -1
  210. package/src/web/utils/unistyle.ts +3 -9
  211. package/src/web/variants/getVariants.ts +1 -1
  212. package/src/web/variants/useVariants.ts +1 -1
  213. package/lib/commonjs/components/useMedia.js.map +0 -1
  214. package/lib/commonjs/components/useMedia.web.js.map +0 -1
  215. package/lib/module/components/useMedia.js.map +0 -1
  216. package/lib/module/components/useMedia.web.js.map +0 -1
  217. package/lib/typescript/src/components/useMedia.d.ts.map +0 -1
  218. package/lib/typescript/src/components/useMedia.web.d.ts.map +0 -1
  219. /package/lib/commonjs/{components → hooks}/useMedia.js +0 -0
  220. /package/lib/commonjs/{components → hooks}/useMedia.web.js +0 -0
  221. /package/lib/module/{components → hooks}/useMedia.js +0 -0
  222. /package/lib/module/{components → hooks}/useMedia.web.js +0 -0
  223. /package/lib/typescript/src/{components → hooks}/useMedia.d.ts +0 -0
  224. /package/lib/typescript/src/{components → hooks}/useMedia.web.d.ts +0 -0
  225. /package/src/{components → hooks}/useMedia.ts +0 -0
  226. /package/src/{components → hooks}/useMedia.web.ts +0 -0
@@ -0,0 +1,72 @@
1
+ import React, { forwardRef, useRef } from 'react'
2
+ import { Pressable as NativePressableReactNative } from 'react-native'
3
+ import type { PressableProps as Props, View } from 'react-native'
4
+ import { UnistylesShadowRegistry } from '../specs'
5
+ import { getId } from '../core'
6
+
7
+ type PressableProps = Props & {
8
+ rawStyle?: Array<any>
9
+ variants?: Record<string, string | boolean>
10
+ }
11
+
12
+ export const Pressable = forwardRef<View, PressableProps>(({ variants, style, rawStyle, ...props }, passedRef) => {
13
+ const storedRef = useRef<View | null>()
14
+
15
+ return (
16
+ <NativePressableReactNative
17
+ {...props}
18
+ ref={ref => {
19
+ storedRef.current = ref
20
+ const styleResult = typeof style === 'function'
21
+ ? style({ pressed: false })
22
+ : style
23
+ const fnArgs = typeof styleResult === 'function'
24
+ // @ts-expect-error - this is hidden from TS
25
+ ? styleResult.getBoundArgs()
26
+ : []
27
+
28
+ if (typeof passedRef === 'object' && passedRef !== null) {
29
+ passedRef.current = ref
30
+ }
31
+
32
+ const returnFn = typeof passedRef === 'function'
33
+ ? passedRef(ref)
34
+ : () => {}
35
+
36
+ // @ts-expect-error - this is hidden from TS
37
+ UnistylesShadowRegistry.add(ref, rawStyle ?? [], variants, [fnArgs])
38
+
39
+ return () => {
40
+ // @ts-expect-error - this is hidden from TS
41
+ UnistylesShadowRegistry.remove(ref)
42
+
43
+ if (typeof returnFn === 'function') {
44
+ returnFn()
45
+ }
46
+ }
47
+ }}
48
+ style={state => {
49
+ const styleResult = typeof style === 'function'
50
+ ? style(state)
51
+ : style
52
+ const fnArgs = typeof styleResult === 'function'
53
+ // @ts-expect-error - this is hidden from TS
54
+ ? styleResult.getBoundArgs()
55
+ : []
56
+ const pressId = getId()
57
+
58
+ if (storedRef.current) {
59
+ // @ts-expect-error - this is hidden from TS
60
+ UnistylesShadowRegistry.remove(storedRef.current)
61
+ // @ts-expect-error - this is hidden from TS
62
+ UnistylesShadowRegistry.add(storedRef.current, rawStyle ?? [], variants, [fnArgs], pressId)
63
+ }
64
+
65
+ return typeof styleResult === 'function'
66
+ // @ts-expect-error - this is hidden from TS
67
+ ? styleResult(pressId)
68
+ : styleResult
69
+ }}
70
+ />
71
+ )
72
+ })
@@ -0,0 +1,103 @@
1
+ import React, { forwardRef, useEffect, useRef } from 'react'
2
+ import { Pressable as NativePressableReactNative } from 'react-native'
3
+ import type { PressableProps as Props, View, ViewStyle } from 'react-native'
4
+ import { UnistylesShadowRegistry } from '../specs'
5
+
6
+ type WebPressableState = {
7
+ pressed: boolean,
8
+ hovered: boolean,
9
+ focused: boolean
10
+ }
11
+
12
+ type PressableProps = Props & {
13
+ variants?: Record<string, string | boolean>
14
+ style?: ((state: WebPressableState) => ViewStyle) | ViewStyle,
15
+ }
16
+
17
+ const initialState: WebPressableState = {
18
+ pressed: false,
19
+ hovered: false,
20
+ focused: false
21
+ }
22
+
23
+ const events = {
24
+ 'pointerdown': { pressed: true },
25
+ 'pointerup': { pressed: false },
26
+ 'pointerenter': { hovered: true },
27
+ 'pointerleave': { hovered: false },
28
+ 'focus': { focused: true },
29
+ 'blur': { focused: false }
30
+ } satisfies Partial<Record<keyof HTMLElementEventMap, Partial<WebPressableState>>>
31
+
32
+ export const Pressable = forwardRef<View, PressableProps>(({ variants, style, ...props }, passedRef) => {
33
+ const storedRef = useRef<View | null>()
34
+ const state = useRef<WebPressableState>(initialState)
35
+ const styleRef = useRef(style)
36
+
37
+ useEffect(() => {
38
+ styleRef.current = style
39
+ }, [style])
40
+
41
+ useEffect(() => {
42
+ const handler = (newState: Partial<WebPressableState>) => () => {
43
+ state.current = { ...state.current, ...newState }
44
+
45
+ const styleResult = typeof styleRef.current === 'function'
46
+ ? styleRef.current(state.current)
47
+ : styleRef.current
48
+ const fnArgs = typeof styleResult === 'function'
49
+ // @ts-expect-error - this is hidden from TS
50
+ ? styleResult.getBoundArgs()
51
+ : []
52
+ const extractedResult = typeof styleResult === 'function'
53
+ ? (styleResult as Function)()
54
+ : styleResult
55
+
56
+ // @ts-expect-error - this is hidden from TS
57
+ UnistylesShadowRegistry.add(storedRef.current, [extractedResult], variants, [fnArgs])
58
+ }
59
+
60
+ if (!storedRef.current) {
61
+ return
62
+ }
63
+
64
+ // ref on the web is dom element
65
+ const ref = storedRef.current as unknown as HTMLDivElement
66
+
67
+ Object.entries(events).forEach(([event, state]) => {
68
+ ref.addEventListener(event, handler(state))
69
+ })
70
+
71
+ return () => {
72
+ Object.entries(events).forEach(([event, state]) => {
73
+ ref.removeEventListener(event, handler(state))
74
+ })
75
+ }
76
+ }, [])
77
+
78
+ return (
79
+ <NativePressableReactNative
80
+ {...props}
81
+ ref={ref => {
82
+ storedRef.current = ref
83
+ const styleResult = typeof style === 'function'
84
+ ? style(initialState)
85
+ : style
86
+ const fnArgs = typeof styleResult === 'function'
87
+ // @ts-expect-error - this is hidden from TS
88
+ ? styleResult.getBoundArgs()
89
+ : []
90
+ const extractedResult = typeof styleResult === 'function'
91
+ ? (styleResult as Function)()
92
+ : styleResult
93
+
94
+ if (typeof passedRef === 'object' && passedRef !== null) {
95
+ passedRef.current = ref
96
+ }
97
+
98
+ // @ts-expect-error - this is hidden from TS
99
+ UnistylesShadowRegistry.add(ref, [extractedResult], variants, [fnArgs])
100
+ }}
101
+ />
102
+ )
103
+ })
@@ -1,2 +1,3 @@
1
1
  export { Hide } from './Hide'
2
2
  export { Display } from './Display'
3
+ export { Pressable } from './Pressable'
@@ -0,0 +1,15 @@
1
+ export const getBoundArgs = (fn: Function) => {
2
+ const boundArgs = [] as Array<any>
3
+
4
+ fn.bind = (thisArg, ...args) => {
5
+ boundArgs.push(...args)
6
+
7
+ const newFn = Function.prototype.bind.apply(fn, [thisArg, ...args])
8
+
9
+ newFn.getBoundArgs = () => boundArgs
10
+
11
+ return newFn
12
+ }
13
+
14
+ return fn
15
+ }
@@ -0,0 +1 @@
1
+ export const getId = () => `${Math.random().toString(36).substring(2, 9)}`
package/src/core/index.ts CHANGED
@@ -1 +1,3 @@
1
1
  export { createUnistylesComponent } from './createUnistylesComponent'
2
+ export { getBoundArgs } from './getBoundArgs'
3
+ export { getId } from './getId'
@@ -0,0 +1 @@
1
+ export { useMedia } from './useMedia'
package/src/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export * from './specs'
2
2
  export { mq } from './mq'
3
3
  export type { UnistylesThemes, UnistylesBreakpoints } from './global'
4
- export { createUnistylesComponent } from './core'
4
+ export { createUnistylesComponent, getBoundArgs } from './core'
5
5
  export type { UnistylesVariants } from './types'
6
6
  export * from './components'
package/src/mq.ts CHANGED
@@ -45,18 +45,18 @@ const getMQValue = (value: Nullable<MQValue>) => {
45
45
  */
46
46
  export const mq: MQHandler = {
47
47
  only: {
48
- width: (wMin: Nullable<MQValue> = 0, wMax: MQValue = Infinity) => (`:w[${getMQValue(wMin)}, ${getMQValue(wMax)}]` as unknown as symbol),
49
- height: (hMin: Nullable<MQValue> = 0, hMax: MQValue = Infinity) => (`:h[${getMQValue(hMin)}, ${getMQValue(hMax)}]` as unknown as symbol)
48
+ width: (wMin: Nullable<MQValue> = 0, wMax: MQValue = Number.POSITIVE_INFINITY) => (`:w[${getMQValue(wMin)}, ${getMQValue(wMax)}]` as unknown as symbol),
49
+ height: (hMin: Nullable<MQValue> = 0, hMax: MQValue = Number.POSITIVE_INFINITY) => (`:h[${getMQValue(hMin)}, ${getMQValue(hMax)}]` as unknown as symbol)
50
50
  },
51
- width: (wMin: Nullable<MQValue> = 0, wMax: MQValue = Infinity) => ({
51
+ width: (wMin: Nullable<MQValue> = 0, wMax: MQValue = Number.POSITIVE_INFINITY) => ({
52
52
  and: {
53
- height: (hMin: Nullable<MQValue> = 0, hMax: MQValue = Infinity) =>
53
+ height: (hMin: Nullable<MQValue> = 0, hMax: MQValue = Number.POSITIVE_INFINITY) =>
54
54
  (`:w[${getMQValue(wMin)}, ${getMQValue(wMax)}]:h[${getMQValue(hMin)}, ${getMQValue(hMax)}]` as unknown as symbol)
55
55
  }
56
56
  }),
57
- height: (hMin: Nullable<MQValue> = 0, hMax: MQValue = Infinity) => ({
57
+ height: (hMin: Nullable<MQValue> = 0, hMax: MQValue = Number.POSITIVE_INFINITY) => ({
58
58
  and: {
59
- width: (wMin: Nullable<MQValue> = 0, wMax: MQValue = Infinity) =>
59
+ width: (wMin: Nullable<MQValue> = 0, wMax: MQValue = Number.POSITIVE_INFINITY) =>
60
60
  (`:w[${getMQValue(wMin)}, ${getMQValue(wMax)}]:h[${getMQValue(hMin)}, ${getMQValue(hMax)}]` as unknown as symbol)
61
61
  }
62
62
  })
@@ -1,5 +1,5 @@
1
1
  import type { HybridObject } from 'react-native-nitro-modules'
2
- import { type Dimensions, type Insets } from '../types'
2
+ import type { Dimensions, Insets } from '../types'
3
3
 
4
4
  type ColorScheme = 'dark' | 'light' | 'unspecified'
5
5
  type Orientation = 'portrait' | 'landscape'
@@ -4,10 +4,10 @@ import type { ShadowNode, Unistyle, ViewHandle } from './types'
4
4
 
5
5
  interface ShadowRegistry extends UnistylesShadowRegistrySpec {
6
6
  // Babel API
7
- add(handle?: ViewHandle, styles?: Array<Unistyle>, variants?: Record<string, string | boolean>, args?: Array<Array<any>>): void,
7
+ add(handle?: ViewHandle, styles?: Array<Unistyle>, variants?: Record<string, string | boolean>, args?: Array<Array<any>>, id?: string): void,
8
8
  remove(handle?: ViewHandle): void,
9
9
  // JSI
10
- link(node: ShadowNode, styles?: Array<Unistyle>, variants?: Record<string, string | boolean>, args?: Array<Array<any>>): void,
10
+ link(node: ShadowNode, styles?: Array<Unistyle>, variants?: Record<string, string | boolean>, args?: Array<Array<any>>, id?: string): void,
11
11
  unlink(node: ShadowNode): void
12
12
  }
13
13
 
@@ -19,14 +19,13 @@ const findShadowNodeForHandle = (handle: ViewHandle) => {
19
19
  ?? handle?.getNativeScrollRef?.()?.__internalInstanceHandle?.stateNode?.node
20
20
 
21
21
  if (!node) {
22
- // todo extend log with file name / component name
23
- throw new Error('Could not find shadow node for one of your components')
22
+ throw new Error(`Unistyles: Could not find shadow node for one of your components of type ${handle?.__internalInstanceHandle?.elementType ?? 'unknown'}`)
24
23
  }
25
24
 
26
25
  return node
27
26
  }
28
27
 
29
- HybridShadowRegistry.add = (handle, styles, variants, args) => {
28
+ HybridShadowRegistry.add = (handle, styles, variants, args, id) => {
30
29
  // virtualized nodes can be null
31
30
  if (!handle || !styles || !Array.isArray(styles)) {
32
31
  return
@@ -37,7 +36,7 @@ HybridShadowRegistry.add = (handle, styles, variants, args) => {
37
36
  .filter(style => !style?.initial?.updater)
38
37
  .filter(Boolean)
39
38
 
40
- HybridShadowRegistry.link(findShadowNodeForHandle(handle), filteredStyles, variants ?? {}, args ?? [])
39
+ HybridShadowRegistry.link(findShadowNodeForHandle(handle), filteredStyles, variants ?? {}, args ?? [], id)
41
40
  }
42
41
 
43
42
  HybridShadowRegistry.remove = handle => {
@@ -8,7 +8,8 @@ export type ShadowNode = {
8
8
 
9
9
  export type ViewHandle = {
10
10
  __internalInstanceHandle?: {
11
- stateNode?: StateNode
11
+ stateNode?: StateNode,
12
+ elementType?: string
12
13
  },
13
14
  getScrollResponder?: () => {
14
15
  getNativeScrollRef?: () => ({
@@ -1,5 +1,5 @@
1
1
  import type { HybridObject } from 'react-native-nitro-modules'
2
- import { UnistyleDependency } from '../NativePlatform'
2
+ import type { UnistyleDependency } from '../NativePlatform'
3
3
 
4
4
  export interface UnistylesStyleSheet extends HybridObject<{ ios: 'c++', android: 'c++' }> {
5
5
  readonly hairlineWidth: number
@@ -6,8 +6,9 @@ import type { UnistylesBreakpoints, UnistylesThemes } from '../../global'
6
6
  import type { CreateUnistylesStyleSheet } from '../../types'
7
7
 
8
8
  type UnistylesSettings = {
9
- adaptiveThemes?: boolean,
10
- initialTheme?: (() => keyof UnistylesThemes) | keyof UnistylesThemes
9
+ initialTheme: (() => keyof UnistylesThemes) | keyof UnistylesThemes
10
+ } | {
11
+ adaptiveThemes: boolean
11
12
  }
12
13
 
13
14
  export type UnistylesConfig = {
@@ -1,8 +1,7 @@
1
1
  import type { TurboModule } from 'react-native'
2
2
  import { TurboModuleRegistry } from 'react-native'
3
3
 
4
- // this is empty spec for TurboModule that is required to hook
5
- // Unistyles to Fabric
4
+ // this is empty spec for TurboModule that is required to hook Unistyles to Fabric
6
5
  interface Spec extends TurboModule {}
7
6
 
8
7
  TurboModuleRegistry.get<Spec>('Unistyles')
@@ -6,7 +6,7 @@ import type { UnistylesNativeMiniRuntime } from '../NativePlatform'
6
6
  type ColorScheme = 'light' | 'dark' | 'unspecified'
7
7
  type Orientation = 'portrait' | 'landscape'
8
8
 
9
- // used for Nitro. It's Native + Cxx types
9
+ // used for Nitro. It's (Native + Cxx) type
10
10
  export interface UnistylesCxxMiniRuntime extends UnistylesNativeMiniRuntime {
11
11
  readonly themeName?: string,
12
12
  readonly breakpoint?: string,
@@ -3,7 +3,7 @@ import { NitroModules } from 'react-native-nitro-modules'
3
3
  import type { UnistylesRuntime as UnistylesRuntimeSpec, UnistylesMiniRuntime } from './UnistylesRuntime.nitro'
4
4
  import type { AppBreakpoint, AppTheme, AppThemeName, Color, ColorScheme, Orientation } from '../types'
5
5
  import { attachStatusBarJSMethods, type UnistylesStatusBar } from '../StatusBar'
6
- import { type UnistylesNavigationBar } from '../NavigtionBar'
6
+ import type { UnistylesNavigationBar } from '../NavigtionBar'
7
7
  import type { AndroidContentSizeCategory, IOSContentSizeCategory, UnistylesTheme } from '../../types'
8
8
  import { isIOS } from '../../common'
9
9
  import type { UnistylesThemes } from '../../global'
@@ -1,5 +1 @@
1
- import type { ReactElement } from 'react'
2
-
3
- export const getSSRUnistyles = () => [] as Array<ReactElement>
4
-
5
1
  export * from '../web'
@@ -2,3 +2,4 @@ export type Optional<T> = T | undefined
2
2
  export type Nullable<T> = T | null
3
3
  export type SafeReturnType<T> = T extends (...args: any) => infer R ? R : T
4
4
  export type PartialBy<T, K> = Omit<T, K & keyof T> & Partial<Pick<T, K & keyof T>>
5
+ export type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never
@@ -1,4 +1,4 @@
1
- export type { Optional, Nullable } from './common'
1
+ export type { Optional, Nullable, UnionToIntersection } from './common'
2
2
  export type {
3
3
  NestedStylePairs,
4
4
  UnistylesTheme,
package/src/utils.ts CHANGED
@@ -6,7 +6,7 @@ export const deepMergeObjects = <T extends Record<PropertyKey, any>>(...sources:
6
6
  const sourceValue = source[key]
7
7
  const targetValue = target[key]
8
8
 
9
- if (Object(sourceValue) == sourceValue && Object(targetValue) === targetValue) {
9
+ if (Object(sourceValue) === sourceValue && Object(targetValue) === targetValue) {
10
10
  // @ts-expect-error - can't assign to generic
11
11
  target[key] = deepMergeObjects(targetValue, sourceValue)
12
12
 
@@ -1,5 +1,6 @@
1
1
  import type { FilterFunction, TextStyle, ViewStyle } from 'react-native'
2
2
  import type { ToDeepUnistyles } from '../../types/stylesheet'
3
+ import type { UnionToIntersection } from '../../types'
3
4
 
4
5
  export type ShadowOffset = ToDeepUnistyles<{ width: number, height: number }>
5
6
 
@@ -15,7 +16,6 @@ export type AllShadow = TextShadow & BoxShadow
15
16
 
16
17
  export type AllShadowKeys = keyof AllShadow
17
18
 
18
- type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never
19
19
  type FilterKeys = keyof UnionToIntersection<FilterFunction>
20
20
 
21
21
  export type Filters = {
@@ -35,8 +35,8 @@ export const normalizeColor = (color: string, opacity = 1) => {
35
35
  if (hex.length === 8) {
36
36
  const [r = 0, g = 0, b = 0, a = 1] = hex
37
37
  .split(/(?=(?:..)*$)/)
38
- .map(x => parseInt(x, 16))
39
- .filter(num => !isNaN(num))
38
+ .map(x => Number.parseInt(x, 16))
39
+ .filter(num => !Number.isNaN(num))
40
40
 
41
41
  return `rgba(${r},${g},${b},${(a / 255) * opacity})`
42
42
  }
package/src/web/create.ts CHANGED
@@ -1,11 +1,15 @@
1
1
  import type { ReactNativeStyleSheet } from '../types'
2
2
  import type { StyleSheetWithSuperPowers, StyleSheet } from '../types/stylesheet'
3
- import { assignSecrets, reduceObject, getStyles } from './utils'
3
+ import { assignSecrets, reduceObject, getStyles, error } from './utils'
4
4
  import { deepMergeObjects } from '../utils'
5
5
  import { UnistylesRuntime } from './runtime'
6
6
  import { createUseVariants, getVariants } from './variants'
7
7
 
8
- export const create = (stylesheet: StyleSheetWithSuperPowers<StyleSheet>) => {
8
+ export const create = (stylesheet: StyleSheetWithSuperPowers<StyleSheet>, id?: string) => {
9
+ if (!id) {
10
+ throw error('Unistyles is not initialized correctly. Please add babel plugin to your babel config.')
11
+ }
12
+
9
13
  const computedStylesheet = typeof stylesheet === 'function'
10
14
  ? stylesheet(UnistylesRuntime.theme, UnistylesRuntime.miniRuntime)
11
15
  : stylesheet
package/src/web/index.ts CHANGED
@@ -12,6 +12,13 @@ export const StyleSheet = {
12
12
  right: 0,
13
13
  bottom: 0,
14
14
  },
15
+ absoluteFillObject: {
16
+ position: 'absolute',
17
+ left: 0,
18
+ top: 0,
19
+ right: 0,
20
+ bottom: 0
21
+ },
15
22
  compose: (a: object, b: object) => deepMergeObjects(a, b),
16
23
  flatten: (...styles: Array<object>) => deepMergeObjects(...styles),
17
24
  hairlineWidth: 1
@@ -20,6 +27,3 @@ export const StyleSheet = {
20
27
  export { UnistylesRuntime } from './runtime'
21
28
  export { UnistylesShadowRegistry } from './shadowRegistry'
22
29
  export * from './mock'
23
-
24
- // TODO: Work on SSR
25
- export const getSSRUnistyles = () => []
@@ -17,6 +17,7 @@ class UnistylesListenerBuilder {
17
17
  }
18
18
 
19
19
  this.isInitialized = true
20
+
20
21
  UnistylesRuntime.darkMedia?.addEventListener('change', event => {
21
22
  if (!event.matches) {
22
23
  return
@@ -39,6 +40,7 @@ class UnistylesListenerBuilder {
39
40
  this.emitChange(UnistyleDependency.Theme)
40
41
  }
41
42
  })
43
+
42
44
  window.addEventListener('orientationchange', () => this.emitChange(UnistyleDependency.Orientation))
43
45
  window.addEventListener('resize', () => this.emitChange(UnistyleDependency.Dimensions))
44
46
  }
@@ -153,7 +153,7 @@ class UnistylesRegistryBuilder {
153
153
  hash: `${hash}${key.replace('_', ':')}`,
154
154
  key: pseudoKey,
155
155
  value: pseudoValue,
156
- sheet: this.styleTag.sheet!
156
+ sheet: this.styleTag.sheet as CSSStyleSheet
157
157
  })
158
158
  })
159
159
 
@@ -5,7 +5,7 @@ import { WebContentSizeCategory } from '../types'
5
5
  import { UnistylesListener } from './listener'
6
6
  import { NavigationBar, StatusBar } from './mock'
7
7
  import { UnistylesState } from './state'
8
- import { isServer, schemeToTheme } from './utils'
8
+ import { error, isServer, schemeToTheme } from './utils'
9
9
 
10
10
  class UnistylesRuntimeBuilder {
11
11
  lightMedia = this.getLightMedia()
@@ -152,6 +152,10 @@ class UnistylesRuntimeBuilder {
152
152
  }
153
153
 
154
154
  setTheme = (themeName: AppThemeName) => {
155
+ if (this.hasAdaptiveThemes) {
156
+ throw error(`You're trying to set theme to: '${themeName}', but adaptiveThemes are enabled.`)
157
+ }
158
+
155
159
  if (themeName === UnistylesRuntime.themeName) {
156
160
  return
157
161
  }
@@ -185,21 +189,17 @@ class UnistylesRuntimeBuilder {
185
189
  const oldTheme = UnistylesState.themes.get(themeName)
186
190
 
187
191
  if (!oldTheme) {
188
- throw new Error(`🦄 Theme "${themeName}" is not registered!`)
192
+ throw error(`Unistyles: You're trying to update theme "${themeName}" but it wasn't registered.`)
189
193
  }
190
194
 
191
195
  UnistylesState.themes.set(themeName, updater(oldTheme))
192
196
  }
193
197
 
194
198
  getTheme = (themeName = this.themeName) => {
195
- if (!themeName) {
196
- throw new Error('🦄 No theme selected!')
197
- }
198
-
199
- const theme = UnistylesState.themes.get(themeName)
199
+ const theme = UnistylesState.themes.get(themeName ?? '')
200
200
 
201
- if (!theme) {
202
- throw new Error(`🦄 Theme "${this.themeName}" is not registered!`)
201
+ if (!themeName || !theme) {
202
+ throw error(`You're trying to get theme "${themeName}" but it wasn't registered.`)
203
203
  }
204
204
 
205
205
  return theme
@@ -65,7 +65,7 @@ class UnistylesShadowRegistryBuilder {
65
65
  const parsedStyles = styles.flatMap((style, styleIndex) => extractSecrets(style).map(secret => {
66
66
  const { __uni__key, __uni__stylesheet, __uni__variants, __uni__args = [], __uni__refs } = secret
67
67
  const newComputedStylesheet = UnistylesRegistry.getComputedStylesheet(__uni__stylesheet)
68
- const style = newComputedStylesheet[__uni__key]!
68
+ const style = newComputedStylesheet[__uni__key] as (UnistylesValues | ((...args: any) => UnistylesValues))
69
69
  const variants = _variants && Object.keys(_variants).length > 0 ? _variants : __uni__variants
70
70
  const args = _args[styleIndex] ? _args[styleIndex] : __uni__args
71
71
  const result = typeof style === 'function'
@@ -93,7 +93,7 @@ class UnistylesShadowRegistryBuilder {
93
93
  }
94
94
 
95
95
  const newComputedStyleSheet = UnistylesRegistry.getComputedStylesheet(__uni__stylesheet)
96
- const newValue = newComputedStyleSheet[__uni__key]!
96
+ const newValue = newComputedStyleSheet[__uni__key] as (UnistylesValues | ((...args: any) => UnistylesValues))
97
97
  const result = typeof newValue === 'function'
98
98
  ? newValue(...args)
99
99
  : newValue
package/src/web/state.ts CHANGED
@@ -3,9 +3,12 @@ import type { UnistylesConfig } from '../specs/StyleSheet'
3
3
  import type { AppBreakpoint, AppTheme, AppThemeName } from '../specs/types'
4
4
  import type { UnistylesBreakpoints, UnistylesThemes } from '../global'
5
5
  import { UnistylesRuntime } from './runtime'
6
- import { isServer, schemeToTheme } from './utils'
6
+ import { error, isServer, schemeToTheme } from './utils'
7
7
  import { UnistylesListener } from './listener'
8
8
  import { UnistyleDependency } from '../specs/NativePlatform'
9
+ import type { UnionToIntersection } from '../types'
10
+
11
+ type UnistylesSettings = Partial<UnionToIntersection<Required<UnistylesConfig>['settings']>>
9
12
 
10
13
  class UnistylesStateBuilder {
11
14
  themes = new Map<string, UnistylesTheme>()
@@ -28,7 +31,10 @@ class UnistylesStateBuilder {
28
31
  init = (config: UnistylesConfig) => {
29
32
  this.initThemes(config.themes)
30
33
  this.initBreakpoints(config.breakpoints)
31
- this.initSettings(config.settings)
34
+
35
+ if (config.settings) {
36
+ this.initSettings(config.settings as UnistylesSettings)
37
+ }
32
38
 
33
39
  if (isServer()) {
34
40
  return
@@ -43,37 +49,50 @@ class UnistylesStateBuilder {
43
49
  })
44
50
  }
45
51
 
46
- private initSettings = (settings: UnistylesConfig['settings']) => {
52
+ private initSettings = (settings: UnistylesSettings) => {
47
53
  this.hasAdaptiveThemes = settings?.adaptiveThemes ?? false
48
- const themeNames = Array.from(this.themes.keys()) as Array<AppThemeName>
49
-
50
- // Single theme + no settings
51
- if (!settings?.adaptiveThemes && !settings?.initialTheme && themeNames.length === 1) {
52
- this.themeName = themeNames[0]
53
54
 
54
- return
55
- }
56
-
57
- // No settings
58
- if (!settings?.adaptiveThemes && !settings?.initialTheme) {
59
- throw new Error('🦄 You need to specify either "initialTheme" or "adaptiveThemes" in your config')
55
+ if (settings.initialTheme && settings.adaptiveThemes) {
56
+ throw error('You\'re trying to set initial theme and enable adaptiveThemes, but these options are mutually exclusive.')
60
57
  }
61
58
 
62
59
  // Adaptive themes
63
60
  if (settings.adaptiveThemes) {
61
+ if (!this.themes.get('light') || !this.themes.get('dark')) {
62
+ throw error(`You're trying to enable adaptiveThemes, but you didn't register both 'light' and 'dark' themes.`)
63
+ }
64
+
64
65
  this.themeName = schemeToTheme(UnistylesRuntime.colorScheme) as AppThemeName
65
66
 
66
67
  return
67
68
  }
68
69
 
69
- // Initial theme
70
- this.themeName = typeof settings.initialTheme === 'function' ? settings.initialTheme() : settings.initialTheme
70
+ if (settings.initialTheme) {
71
+ const initialTheme = typeof settings.initialTheme === 'function'
72
+ ? settings.initialTheme()
73
+ : settings.initialTheme
74
+
75
+ if (!this.themes.get(initialTheme)) {
76
+ throw error(`You're trying to select theme "${initialTheme}" but it wasn't registered.`)
77
+ }
78
+
79
+ this.themeName = initialTheme
80
+ }
71
81
  }
72
82
 
73
83
  private initBreakpoints = (breakpoints = {} as UnistylesBreakpoints) => {
74
84
  this.breakpoints = breakpoints
85
+ const breakpointsEntries = Object.entries(breakpoints)
86
+
87
+ if (breakpointsEntries.length === 0) {
88
+ throw error('StyleSheet.configure\'s breakpoints can\'t be empty.')
89
+ }
90
+
91
+ if (breakpointsEntries?.[0]?.[1] !== 0) {
92
+ throw error('StyleSheet.configure\'s first breakpoint must start from 0.')
93
+ }
75
94
 
76
- Object.entries(breakpoints)
95
+ breakpointsEntries
77
96
  .sort(([, a], [, b]) => a - b)
78
97
  .forEach(([breakpoint, value]) => {
79
98
  if (isServer()) {
@@ -7,7 +7,7 @@ export const keyInObject = <T extends Record<string, any>>(obj: T, key: Property
7
7
 
8
8
  export const isServer = () => typeof window === 'undefined'
9
9
 
10
- export const warn = (message: string) => console.warn(`🦄 [react-native-unistyles] ${message}`)
10
+ export const error = (message: string) => new Error(`Unistyles: ${message}`)
11
11
 
12
12
  export const equal = <T>(a: T, b: T) => {
13
13
  if (Object.is(a, b)) {