@niibase/uniwind 1.0.0 → 1.0.11

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 (107) hide show
  1. package/dist/common/components/react-native-gesture-handler/index.js +122 -0
  2. package/dist/common/components/react-native-gesture-handler/native/BaseButton.js +18 -0
  3. package/dist/common/components/react-native-gesture-handler/native/BorderlessButton.js +18 -0
  4. package/dist/common/components/react-native-gesture-handler/native/DrawerLayoutAndroid.js +18 -0
  5. package/dist/common/components/react-native-gesture-handler/native/FlatList.js +30 -0
  6. package/dist/common/components/react-native-gesture-handler/native/GestureHandlerRootView.js +18 -0
  7. package/dist/common/components/react-native-gesture-handler/native/Pressable.js +29 -0
  8. package/dist/common/components/react-native-gesture-handler/native/PureNativeButton.js +18 -0
  9. package/dist/common/components/react-native-gesture-handler/native/RawButton.js +18 -0
  10. package/dist/common/components/react-native-gesture-handler/native/RectButton.js +18 -0
  11. package/dist/common/components/react-native-gesture-handler/native/RefreshControl.js +27 -0
  12. package/dist/common/components/react-native-gesture-handler/native/ScrollView.js +23 -0
  13. package/dist/common/components/react-native-gesture-handler/native/Switch.js +32 -0
  14. package/dist/common/components/react-native-gesture-handler/native/Text.js +36 -0
  15. package/dist/common/components/react-native-gesture-handler/native/TextInput.js +53 -0
  16. package/dist/common/components/react-native-gesture-handler/native/TouchableNativeFeedback.js +32 -0
  17. package/dist/common/components/react-native-gesture-handler/native/TouchableOpacity.js +32 -0
  18. package/dist/common/components/react-native-gesture-handler/native/TouchableWithoutFeedback.js +32 -0
  19. package/dist/common/components/react-native-svg/index.js +14 -0
  20. package/dist/common/components/react-native-svg/native/Svg.js +18 -0
  21. package/dist/common/components/react-native-svg/web/Svg.js +17 -0
  22. package/dist/common/core/native/runtime.js +2 -1
  23. package/dist/common/core/native/store.js +33 -3
  24. package/dist/metro/index.cjs +22 -6
  25. package/dist/metro/index.mjs +20 -4
  26. package/dist/metro/metro-transformer.cjs +56 -19
  27. package/dist/metro/metro-transformer.mjs +56 -19
  28. package/dist/module/components/react-native-gesture-handler/index.d.ts +0 -0
  29. package/dist/module/components/react-native-gesture-handler/index.js +120 -0
  30. package/dist/module/components/react-native-gesture-handler/native/BaseButton.d.ts +3 -0
  31. package/dist/module/components/react-native-gesture-handler/native/BaseButton.js +15 -0
  32. package/dist/module/components/react-native-gesture-handler/native/BorderlessButton.d.ts +3 -0
  33. package/dist/module/components/react-native-gesture-handler/native/BorderlessButton.js +18 -0
  34. package/dist/module/components/react-native-gesture-handler/native/DrawerLayoutAndroid.d.ts +5 -0
  35. package/dist/module/components/react-native-gesture-handler/native/DrawerLayoutAndroid.js +18 -0
  36. package/dist/module/components/react-native-gesture-handler/native/FlatList.d.ts +4 -0
  37. package/dist/module/components/react-native-gesture-handler/native/FlatList.js +27 -0
  38. package/dist/module/components/react-native-gesture-handler/native/GestureHandlerRootView.d.ts +3 -0
  39. package/dist/module/components/react-native-gesture-handler/native/GestureHandlerRootView.js +18 -0
  40. package/dist/module/components/react-native-gesture-handler/native/Pressable.d.ts +3 -0
  41. package/dist/module/components/react-native-gesture-handler/native/Pressable.js +29 -0
  42. package/dist/module/components/react-native-gesture-handler/native/PureNativeButton.d.ts +3 -0
  43. package/dist/module/components/react-native-gesture-handler/native/PureNativeButton.js +15 -0
  44. package/dist/module/components/react-native-gesture-handler/native/RawButton.d.ts +3 -0
  45. package/dist/module/components/react-native-gesture-handler/native/RawButton.js +15 -0
  46. package/dist/module/components/react-native-gesture-handler/native/RectButton.d.ts +3 -0
  47. package/dist/module/components/react-native-gesture-handler/native/RectButton.js +15 -0
  48. package/dist/module/components/react-native-gesture-handler/native/RefreshControl.d.ts +3 -0
  49. package/dist/module/components/react-native-gesture-handler/native/RefreshControl.js +24 -0
  50. package/dist/module/components/react-native-gesture-handler/native/ScrollView.d.ts +3 -0
  51. package/dist/module/components/react-native-gesture-handler/native/ScrollView.js +20 -0
  52. package/dist/module/components/react-native-gesture-handler/native/Switch.d.ts +3 -0
  53. package/dist/module/components/react-native-gesture-handler/native/Switch.js +26 -0
  54. package/dist/module/components/react-native-gesture-handler/native/Text.d.ts +2 -0
  55. package/dist/module/components/react-native-gesture-handler/native/Text.js +33 -0
  56. package/dist/module/components/react-native-gesture-handler/native/TextInput.d.ts +3 -0
  57. package/dist/module/components/react-native-gesture-handler/native/TextInput.js +50 -0
  58. package/dist/module/components/react-native-gesture-handler/native/TouchableNativeFeedback.d.ts +2 -0
  59. package/dist/module/components/react-native-gesture-handler/native/TouchableNativeFeedback.js +32 -0
  60. package/dist/module/components/react-native-gesture-handler/native/TouchableOpacity.d.ts +3 -0
  61. package/dist/module/components/react-native-gesture-handler/native/TouchableOpacity.js +32 -0
  62. package/dist/module/components/react-native-gesture-handler/native/TouchableWithoutFeedback.d.ts +4 -0
  63. package/dist/module/components/react-native-gesture-handler/native/TouchableWithoutFeedback.js +34 -0
  64. package/dist/module/components/react-native-svg/index.d.ts +1 -0
  65. package/dist/module/components/react-native-svg/index.js +10 -0
  66. package/dist/module/components/react-native-svg/native/Svg.d.ts +3 -0
  67. package/dist/module/components/react-native-svg/native/Svg.js +15 -0
  68. package/dist/module/components/react-native-svg/web/Svg.d.ts +3 -0
  69. package/dist/module/components/react-native-svg/web/Svg.js +14 -0
  70. package/dist/module/core/native/runtime.js +2 -6
  71. package/dist/module/core/native/store.d.ts +2 -0
  72. package/dist/module/core/native/store.js +30 -3
  73. package/dist/module/core/types.d.ts +10 -0
  74. package/package.json +6 -1
  75. package/readme.md +3 -0
  76. package/src/components/react-native-gesture-handler/index.ts +121 -0
  77. package/src/components/react-native-gesture-handler/native/BaseButton.tsx +18 -0
  78. package/src/components/react-native-gesture-handler/native/BorderlessButton.tsx +19 -0
  79. package/src/components/react-native-gesture-handler/native/DrawerLayoutAndroid.tsx +20 -0
  80. package/src/components/react-native-gesture-handler/native/FlatList.tsx +29 -0
  81. package/src/components/react-native-gesture-handler/native/GestureHandlerRootView.tsx +20 -0
  82. package/src/components/react-native-gesture-handler/native/Pressable.tsx +31 -0
  83. package/src/components/react-native-gesture-handler/native/PureNativeButton.tsx +16 -0
  84. package/src/components/react-native-gesture-handler/native/RawButton.tsx +16 -0
  85. package/src/components/react-native-gesture-handler/native/RectButton.tsx +16 -0
  86. package/src/components/react-native-gesture-handler/native/RefreshControl.tsx +26 -0
  87. package/src/components/react-native-gesture-handler/native/ScrollView.tsx +22 -0
  88. package/src/components/react-native-gesture-handler/native/Switch.tsx +29 -0
  89. package/src/components/react-native-gesture-handler/native/Text.tsx +40 -0
  90. package/src/components/react-native-gesture-handler/native/TextInput.tsx +53 -0
  91. package/src/components/react-native-gesture-handler/native/TouchableNativeFeedback.tsx +35 -0
  92. package/src/components/react-native-gesture-handler/native/TouchableOpacity.tsx +34 -0
  93. package/src/components/react-native-gesture-handler/native/TouchableWithoutFeedback.tsx +37 -0
  94. package/src/components/react-native-svg/index.ts +12 -0
  95. package/src/components/react-native-svg/native/Svg.tsx +16 -0
  96. package/src/components/react-native-svg/web/Svg.tsx +14 -0
  97. package/src/core/native/runtime.ts +2 -6
  98. package/src/core/native/store.ts +51 -5
  99. package/src/core/types.ts +10 -0
  100. package/src/metro/compileVirtual.ts +5 -1
  101. package/src/metro/processor/mq.ts +15 -10
  102. package/src/metro/processor/processor.ts +55 -16
  103. package/src/metro/resolvers.ts +25 -3
  104. package/src/metro/types.ts +3 -2
  105. package/src/metro/withUniwindConfig.ts +1 -1
  106. package/types.d.ts +38 -0
  107. package/uniwind.css +1 -6
@@ -0,0 +1,34 @@
1
+ import { useState } from 'react'
2
+ import { TouchableOpacity as RNGHTouchableOpacity, TouchableOpacityProps } from 'react-native-gesture-handler'
3
+ import { ComponentState } from '../../../core/types'
4
+ import { useStyle } from '../../native/useStyle'
5
+ import { copyComponentProperties } from '../../utils'
6
+
7
+ export const TouchableOpacity = copyComponentProperties(
8
+ RNGHTouchableOpacity,
9
+ (props: TouchableOpacityProps) => {
10
+ const [isPressed, setIsPressed] = useState(false)
11
+ const state = {
12
+ isDisabled: Boolean(props.disabled),
13
+ isPressed,
14
+ } satisfies ComponentState
15
+ const style = useStyle(props.className, state)
16
+
17
+ return (
18
+ <RNGHTouchableOpacity
19
+ {...props}
20
+ style={[style, props.style]}
21
+ onPressIn={() => {
22
+ setIsPressed(true)
23
+ props.onPressIn?.()
24
+ }}
25
+ onPressOut={() => {
26
+ setIsPressed(false)
27
+ props.onPressOut?.()
28
+ }}
29
+ />
30
+ )
31
+ },
32
+ )
33
+
34
+ export default TouchableOpacity
@@ -0,0 +1,37 @@
1
+ import { useState } from 'react'
2
+ import {
3
+ TouchableWithoutFeedback as RNGHTouchableWithoutFeedback,
4
+ TouchableWithoutFeedbackProps,
5
+ } from 'react-native-gesture-handler'
6
+ import { ComponentState } from '../../../core/types'
7
+ import { useStyle } from '../../native/useStyle'
8
+ import { copyComponentProperties } from '../../utils'
9
+
10
+ export const TouchableWithoutFeedback = copyComponentProperties(
11
+ RNGHTouchableWithoutFeedback,
12
+ (props: TouchableWithoutFeedbackProps) => {
13
+ const [isPressed, setIsPressed] = useState(false)
14
+ const state = {
15
+ isDisabled: Boolean(props.disabled),
16
+ isPressed,
17
+ } satisfies ComponentState
18
+ const style = useStyle(props.className, state)
19
+
20
+ return (
21
+ <RNGHTouchableWithoutFeedback
22
+ {...props}
23
+ style={[style, props.style]}
24
+ onPressIn={() => {
25
+ setIsPressed(true)
26
+ props.onPressIn?.()
27
+ }}
28
+ onPressOut={() => {
29
+ setIsPressed(false)
30
+ props.onPressOut?.()
31
+ }}
32
+ />
33
+ )
34
+ },
35
+ )
36
+
37
+ export default TouchableWithoutFeedback
@@ -0,0 +1,12 @@
1
+ // Re-export everything from react-native-svg
2
+ import * as Svg from 'react-native-svg'
3
+
4
+ module.exports = {
5
+ ...Svg,
6
+ get Svg() {
7
+ return require('./native/Svg').Svg
8
+ },
9
+ get default() {
10
+ return require('./native/Svg').default
11
+ },
12
+ }
@@ -0,0 +1,16 @@
1
+ import { Svg as RNSvg, SvgProps } from 'react-native-svg'
2
+ import { useStyle } from '../../native/useStyle'
3
+ import { copyComponentProperties } from '../../utils'
4
+
5
+ export const Svg = copyComponentProperties(RNSvg, (props: SvgProps) => {
6
+ const style = useStyle(props.className)
7
+
8
+ return (
9
+ <RNSvg
10
+ {...props}
11
+ style={[style, props.style]}
12
+ />
13
+ )
14
+ })
15
+
16
+ export default Svg
@@ -0,0 +1,14 @@
1
+ import { Svg as RNSvg, SvgProps } from 'react-native-svg'
2
+ import { copyComponentProperties } from '../../utils'
3
+ import { toRNWClassName } from '../../web/rnw'
4
+
5
+ export const Svg = copyComponentProperties(RNSvg, (props: SvgProps) => {
6
+ return (
7
+ <RNSvg
8
+ {...props}
9
+ style={[toRNWClassName(props.className), props.style]}
10
+ />
11
+ )
12
+ })
13
+
14
+ export default Svg
@@ -1,4 +1,5 @@
1
1
  import { Appearance, Dimensions, I18nManager, PixelRatio, StyleSheet } from 'react-native'
2
+ import { initialWindowMetrics } from 'react-native-safe-area-context'
2
3
  import { ColorScheme, Orientation } from '../../types'
3
4
  import type { UniwindRuntime as UniwindRuntimeType } from '../types'
4
5
  import { colorMix, lightDark } from './native-utils'
@@ -17,12 +18,7 @@ export const UniwindRuntime = {
17
18
  fontScale: value => value * PixelRatio.getFontScale(),
18
19
  hairlineWidth: StyleSheet.hairlineWidth,
19
20
  rtl: I18nManager.isRTL,
20
- insets: {
21
- top: 0,
22
- left: 0,
23
- bottom: 0,
24
- right: 0,
25
- },
21
+ insets: initialWindowMetrics?.insets ?? { top: 0, left: 0, bottom: 0, right: 0 },
26
22
  colorMix,
27
23
  pixelRatio: value => value * PixelRatio.get(),
28
24
  cubicBezier: () => '',
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable max-depth */
2
2
  import { Dimensions, Platform } from 'react-native'
3
- import { Orientation, StyleDependency } from '../../types'
3
+ import { ColorScheme, Orientation, StyleDependency } from '../../types'
4
4
  import { UniwindListener } from '../listener'
5
5
  import { ComponentState, CSSVariables, GenerateStyleSheetsCallback, RNStyle, Style, StyleSheets, ThemeName } from '../types'
6
6
  import { cloneWithAccessors } from './native-utils'
@@ -17,6 +17,16 @@ class UniwindStoreBuilder {
17
17
  vars = {} as Record<string, unknown>
18
18
  runtimeThemeVariables = new Map<ThemeName, CSSVariables>()
19
19
  private stylesheet = {} as StyleSheets
20
+ private varsWithMediaQueries = [] as Array<[
21
+ string,
22
+ Array<{
23
+ value: unknown
24
+ minWidth: number | null
25
+ maxWidth: number | null
26
+ orientation: Orientation | null
27
+ colorScheme: ColorScheme | null
28
+ }>,
29
+ ]>
20
30
  private cache = new Map<string, StylesResult>()
21
31
  private generateStyleSheetCallbackResult: ReturnType<GenerateStyleSheetsCallback> | null = null
22
32
 
@@ -53,11 +63,11 @@ class UniwindStoreBuilder {
53
63
  return
54
64
  }
55
65
 
56
- const { scopedVars, stylesheet, vars } = config
57
-
66
+ const { scopedVars, stylesheet, vars, varsWithMediaQueries } = config
67
+ this.vars = varsWithMediaQueries.length > 0 ? { ...vars } : vars
68
+ this.varsWithMediaQueries = varsWithMediaQueries
58
69
  this.generateStyleSheetCallbackResult = config
59
70
  this.stylesheet = stylesheet
60
- this.vars = vars
61
71
 
62
72
  const themeVars = scopedVars[`__uniwind-theme-${this.runtime.currentThemeName}`]
63
73
  const platformVars = scopedVars[`__uniwind-platform-${Platform.OS}`]
@@ -80,11 +90,47 @@ class UniwindStoreBuilder {
80
90
  }
81
91
  }
82
92
 
93
+ private resolveMediaQueryVars(dependencies: Set<StyleDependency>) {
94
+ for (const [varName, mqVariants] of this.varsWithMediaQueries) {
95
+ let bestMatch: { value: unknown; minWidth: number | null } | null = null
96
+
97
+ for (const variant of mqVariants) {
98
+ if (variant.orientation !== null) dependencies.add(StyleDependency.Orientation)
99
+ if (variant.maxWidth !== null || variant.minWidth !== null) dependencies.add(StyleDependency.Dimensions)
100
+ if (variant.colorScheme !== null) {
101
+ dependencies.add(StyleDependency.ColorScheme)
102
+ dependencies.add(StyleDependency.Theme)
103
+ }
104
+
105
+ if (
106
+ (variant.minWidth !== null && variant.minWidth > this.runtime.screen.width)
107
+ || (variant.maxWidth !== null && variant.maxWidth !== Number.MAX_VALUE && variant.maxWidth < this.runtime.screen.width)
108
+ || (variant.orientation !== null && this.runtime.orientation !== variant.orientation)
109
+ || (variant.colorScheme !== null && this.runtime.currentThemeName !== variant.colorScheme)
110
+ ) {
111
+ continue
112
+ }
113
+
114
+ if (bestMatch === null || (variant.minWidth ?? 0) > (bestMatch.minWidth ?? 0)) bestMatch = variant
115
+ }
116
+
117
+ if (bestMatch !== null) {
118
+ Object.defineProperty(this.vars, varName, {
119
+ configurable: true,
120
+ enumerable: true,
121
+ get: () => bestMatch.value,
122
+ })
123
+ }
124
+ }
125
+
126
+ return this.vars
127
+ }
128
+
83
129
  private resolveStyles(classNames: string, state?: ComponentState) {
84
130
  const result = {} as Record<string, any>
85
- let vars = this.vars
86
131
  const dependencies = new Set<StyleDependency>()
87
132
  const bestBreakpoints = new Map<string, Style>()
133
+ let vars = this.resolveMediaQueryVars(dependencies)
88
134
 
89
135
  for (const className of classNames.split(' ')) {
90
136
  if (!(className in this.stylesheet)) {
package/src/core/types.ts CHANGED
@@ -25,6 +25,16 @@ export type GenerateStyleSheetsCallback = (rt: UniwindRuntime) => {
25
25
  stylesheet: StyleSheets
26
26
  vars: Record<string, unknown>
27
27
  scopedVars: Partial<Record<string, Record<string, unknown>>>
28
+ varsWithMediaQueries: Array<[
29
+ string,
30
+ Array<{
31
+ value: unknown
32
+ minWidth: number | null
33
+ maxWidth: number | null
34
+ orientation: Orientation | null
35
+ colorScheme: ColorScheme | null
36
+ }>,
37
+ ]>
28
38
  }
29
39
 
30
40
  type UserThemes = UniwindConfig extends { themes: infer T extends readonly string[] } ? T
@@ -6,7 +6,7 @@ import { Logger } from './logger'
6
6
  import { polyfillWeb } from './polyfillWeb'
7
7
  import { ProcessorBuilder } from './processor'
8
8
  import { Platform, Polyfills } from './types'
9
- import { serializeJSObject } from './utils'
9
+ import { serialize, serializeJSObject } from './utils'
10
10
 
11
11
  type CompileVirtualConfig = {
12
12
  cssPath: string
@@ -59,6 +59,9 @@ export const compileVirtual = async ({ css, cssPath, platform, themes, polyfills
59
59
  serializeJSObject(scopedVars, (key, value) => `get "${key}"() { return ${value} }`),
60
60
  ]),
61
61
  )
62
+ const varsWithMediaQueries = Object.entries(Processor.varsWithMediaQueries)
63
+ .map(([key, value]) => `["${key}", ${serialize(value)}]`)
64
+ .join(',')
62
65
  const serializedScopedVars = Object.entries(scopedVars)
63
66
  .map(([scopedVarsName, scopedVars]) => `"${scopedVarsName}": ({ ${scopedVars} }),`)
64
67
  .join('')
@@ -68,6 +71,7 @@ export const compileVirtual = async ({ css, cssPath, platform, themes, polyfills
68
71
  '({',
69
72
  `scopedVars: ({ ${serializedScopedVars} }),`,
70
73
  `vars: ({ ${currentColorVar} ${vars} }),`,
74
+ `varsWithMediaQueries: ([ ${varsWithMediaQueries} ]),`,
71
75
  `stylesheet: ({ ${stylesheet} }),`,
72
76
  '})',
73
77
  ].join('')
@@ -1,4 +1,4 @@
1
- import { MediaQuery, QueryFeatureFor_MediaFeatureId } from 'lightningcss'
1
+ import { MediaCondition, MediaQuery, QueryFeatureFor_MediaFeatureId } from 'lightningcss'
2
2
  import { ColorScheme, Orientation } from '../../types'
3
3
  import { MediaQueryResolver, Platform } from '../types'
4
4
  import type { ProcessorBuilder } from './processor'
@@ -9,19 +9,26 @@ export class MQ {
9
9
  processMediaQueries(mediaQueries: Array<MediaQuery>) {
10
10
  const mq = this.getInitialMediaQueryResolver()
11
11
 
12
- mediaQueries.forEach(mediaQuery => {
12
+ for (const mediaQuery of mediaQueries) {
13
13
  const { condition, mediaType } = mediaQuery
14
14
 
15
15
  if ([Platform.Android, Platform.iOS, Platform.Native].includes(mediaType as Platform)) {
16
16
  mq.platform = mediaType as Platform
17
-
18
- return
17
+ continue
19
18
  }
20
19
 
21
- if (condition?.type !== 'feature') {
22
- return
23
- }
20
+ if (condition) this.processCondition(condition, mq)
21
+ }
24
22
 
23
+ return mq
24
+ }
25
+
26
+ private processCondition(condition: MediaCondition, mq: MediaQueryResolver) {
27
+ if (condition.type === 'operation') {
28
+ condition.conditions.forEach(nestedCondition => {
29
+ this.processCondition(nestedCondition, mq)
30
+ })
31
+ } else if (condition.type === 'feature') {
25
32
  if (condition.value.type === 'range') {
26
33
  this.processWidthMediaQuery(condition.value, mq)
27
34
  }
@@ -29,9 +36,7 @@ export class MQ {
29
36
  if (condition.value.type === 'plain') {
30
37
  this.processPlainMediaQuery(condition.value, mq)
31
38
  }
32
- })
33
-
34
- return mq
39
+ }
35
40
  }
36
41
 
37
42
  private processWidthMediaQuery(query: QueryFeatureFor_MediaFeatureId & { type: 'range' }, mq: MediaQueryResolver) {
@@ -1,5 +1,5 @@
1
1
  import { Declaration, MediaQuery, Rule, transform } from 'lightningcss'
2
- import { Polyfills, ProcessMetaValues } from '../types'
2
+ import { MediaQueryResolver, Polyfills, ProcessMetaValues } from '../types'
3
3
  import { Color } from './color'
4
4
  import { CSS } from './css'
5
5
  import { Functions } from './functions'
@@ -12,6 +12,7 @@ export class ProcessorBuilder {
12
12
  stylesheets = {} as Record<string, Array<any>>
13
13
  vars = {} as Record<string, any>
14
14
  scopedVars = {} as Record<string, Record<string, any>>
15
+ varsWithMediaQueries = {} as Record<string, Array<any>>
15
16
  CSS = new CSS(this)
16
17
  RN = new RN(this)
17
18
  Var = new Var(this)
@@ -54,6 +55,43 @@ export class ProcessorBuilder {
54
55
  })
55
56
  }
56
57
 
58
+ private storeVarWithMediaQuery(varName: string, value: any, mq: MediaQueryResolver) {
59
+ if (!Array.isArray(this.varsWithMediaQueries[varName])) {
60
+ this.varsWithMediaQueries[varName] = []
61
+ }
62
+
63
+ this.varsWithMediaQueries[varName].push({
64
+ value,
65
+ minWidth: mq.minWidth,
66
+ maxWidth: mq.maxWidth,
67
+ orientation: mq.orientation ? `'${mq.orientation}'` : null,
68
+ colorScheme: mq.colorScheme ? `'${mq.colorScheme}'` : null,
69
+ })
70
+ }
71
+
72
+ private hasMediaQuery(mq: MediaQueryResolver): boolean {
73
+ return mq.minWidth !== 0 || mq.maxWidth !== Number.MAX_VALUE || mq.orientation !== null || mq.colorScheme !== null
74
+ }
75
+
76
+ private processDeclarationValue(
77
+ mq: MediaQueryResolver,
78
+ varName: string,
79
+ processedValue: any,
80
+ context: { isVar: boolean; style: any; important: boolean },
81
+ ) {
82
+ const { isVar, style, important } = context
83
+
84
+ if (isVar && this.hasMediaQuery(mq)) {
85
+ this.storeVarWithMediaQuery(varName, processedValue, mq)
86
+ } else {
87
+ style[varName] = processedValue
88
+ }
89
+
90
+ if (!isVar && important) {
91
+ style.importantProperties.push(varName)
92
+ }
93
+ }
94
+
57
95
  private addDeclaration(declaration: Declaration, important = false) {
58
96
  const isVar = this.declarationConfig.root || this.declarationConfig.className === null
59
97
  const mq = this.MQ.processMediaQueries(this.declarationConfig.mediaQueries)
@@ -90,31 +128,27 @@ export class ProcessorBuilder {
90
128
  this.meta.className = this.declarationConfig.className
91
129
  }
92
130
 
93
- if (declaration.property === 'unparsed') {
94
- style[declaration.value.propertyId.property] = this.CSS.processValue(declaration.value.value)
131
+ const context = { isVar, style, important }
95
132
 
96
- if (!isVar && important) {
97
- style.importantProperties.push(declaration.value.propertyId.property)
98
- }
133
+ if (declaration.property === 'unparsed') {
134
+ const varName = declaration.value.propertyId.property
135
+ const processedValue = this.CSS.processValue(declaration.value.value)
136
+ this.processDeclarationValue(mq, varName, processedValue, context)
99
137
 
100
138
  return
101
139
  }
102
140
 
103
141
  if (declaration.property === 'custom') {
104
- style[declaration.value.name] = this.CSS.processValue(declaration.value.value)
105
-
106
- if (!isVar && important) {
107
- style.importantProperties.push(declaration.value.name)
108
- }
142
+ const varName = declaration.value.name
143
+ const processedValue = this.CSS.processValue(declaration.value.value)
144
+ this.processDeclarationValue(mq, varName, processedValue, context)
109
145
 
110
146
  return
111
147
  }
112
148
 
113
- style[declaration.property] = this.CSS.processValue(declaration.value)
114
-
115
- if (!isVar && important) {
116
- style.importantProperties.push(declaration.property)
117
- }
149
+ const varName = declaration.property
150
+ const processedValue = this.CSS.processValue(declaration.value)
151
+ this.processDeclarationValue(mq, varName, processedValue, context)
118
152
  }
119
153
 
120
154
  private parseRuleRec(rule: Rule<Declaration, MediaQuery>) {
@@ -226,6 +260,11 @@ export class ProcessorBuilder {
226
260
  this.declarationConfig = this.getDeclarationConfig()
227
261
  })
228
262
 
263
+ this.declarationConfig.mediaQueries.splice(
264
+ this.declarationConfig.mediaQueries.length - mediaQueries.length,
265
+ mediaQueries.length,
266
+ )
267
+
229
268
  return
230
269
  }
231
270
 
@@ -1,6 +1,6 @@
1
1
  import { CustomResolutionContext, CustomResolver } from 'metro-resolver'
2
2
  import { basename, resolve, sep } from 'node:path'
3
- import { name } from '../../package.json'
3
+ import { name as packageName } from '../../package.json'
4
4
 
5
5
  type ResolverConfig = {
6
6
  platform: string | null
@@ -11,8 +11,10 @@ type ResolverConfig = {
11
11
 
12
12
  const thisModuleDist = resolve(__dirname, '../../dist')
13
13
  const thisModuleSrc = resolve(__dirname, '../../src')
14
+ const nodeModulesPath = resolve(__dirname, '../../../')
14
15
 
15
16
  const isFromThisModule = (filename: string) => filename.startsWith(thisModuleDist) || filename.startsWith(thisModuleSrc)
17
+ const name = basename(nodeModulesPath) === 'node_modules' ? basename(resolve(__dirname, '../../')) : packageName
16
18
 
17
19
  const SUPPORTED_COMPONENTS = [
18
20
  'ActivityIndicator',
@@ -39,7 +41,8 @@ const SUPPORTED_COMPONENTS = [
39
41
  'VirtualizedList',
40
42
  ]
41
43
 
42
- export const nativeResolver = ({
44
+ export const nativeResolver = (extraComponents: Record<string, string>) =>
45
+ ({
43
46
  context,
44
47
  moduleName,
45
48
  platform,
@@ -59,6 +62,14 @@ export const nativeResolver = ({
59
62
  return resolver(context, `${name}/components`, platform)
60
63
  }
61
64
 
65
+ if (moduleName === 'react-native-gesture-handler') {
66
+ return resolver(context, `${name}/components/react-native-gesture-handler`, platform)
67
+ }
68
+
69
+ if (moduleName === 'react-native-svg') {
70
+ return resolver(context, `${name}/components/react-native-svg`, platform)
71
+ }
72
+
62
73
  if (
63
74
  resolution.filePath.includes(`${sep}react-native${sep}Libraries${sep}`)
64
75
  ) {
@@ -70,10 +81,16 @@ export const nativeResolver = ({
70
81
  }
71
82
  }
72
83
 
84
+ if (moduleName in extraComponents) {
85
+ const componentPath = extraComponents[moduleName]!
86
+ return resolver(context, componentPath, platform)
87
+ }
88
+
73
89
  return resolution
74
90
  }
75
91
 
76
- export const webResolver = ({
92
+ export const webResolver = (extraComponents: Record<string, string>) =>
93
+ ({
77
94
  context,
78
95
  moduleName,
79
96
  platform,
@@ -89,6 +106,11 @@ export const webResolver = ({
89
106
  return resolution
90
107
  }
91
108
 
109
+ if (moduleName in extraComponents) {
110
+ const componentPath = extraComponents[moduleName]!
111
+ return resolver(context, componentPath, platform)
112
+ }
113
+
92
114
  const segments = resolution.filePath.split(sep)
93
115
  const isIndex = segments.at(-1)?.startsWith('index.')
94
116
  const module = segments.at(-2)
@@ -21,14 +21,15 @@ export type UniwindConfig = {
21
21
  cssEntryFile: string
22
22
  themes: Array<string>
23
23
  extraThemes?: Array<string>
24
+ extraComponents?: Record<string, string>
24
25
  dtsFile?: string
25
26
  polyfills?: Polyfills
26
27
  debug?: boolean
27
28
  }
28
29
 
29
30
  export type MediaQueryResolver = {
30
- maxWidth: any
31
- minWidth: any
31
+ maxWidth: number | null
32
+ minWidth: number | null
32
33
  platform: Platform | null
33
34
  rtl: boolean | null
34
35
  important: boolean
@@ -45,7 +45,7 @@ export const withUniwindConfig = <T extends MetroConfig>(
45
45
  ),
46
46
  resolveRequest: (context, moduleName, platform) => {
47
47
  const resolver = config.resolver?.resolveRequest ?? context.resolveRequest
48
- const platformResolver = platform === Platform.Web ? webResolver : nativeResolver
48
+ const platformResolver = (platform === Platform.Web ? webResolver : nativeResolver)(uniwindConfig.extraComponents ?? {})
49
49
  const resolved = platformResolver({
50
50
  context,
51
51
  moduleName,
package/types.d.ts CHANGED
@@ -106,4 +106,42 @@ declare module 'react-native' {
106
106
  interface InputAccessoryViewProps {
107
107
  backgroundColorClassName?: string
108
108
  }
109
+
110
+ interface DrawerLayoutAndroidProps {
111
+ className?: string
112
+ }
113
+ }
114
+
115
+ declare module 'react-native-gesture-handler' {
116
+ // Button components
117
+ interface BaseButtonProps {
118
+ className?: string
119
+ }
120
+
121
+ interface BorderlessButtonProps {
122
+ className?: string
123
+ }
124
+
125
+ interface RawButtonProps {
126
+ className?: string
127
+ }
128
+
129
+ interface RectButtonProps {
130
+ className?: string
131
+ }
132
+
133
+ // Gesture handler specific components
134
+ interface GestureHandlerRootViewProps {
135
+ className?: string
136
+ }
137
+
138
+ interface PressableProps {
139
+ className?: string
140
+ }
141
+ }
142
+
143
+ declare module 'react-native-svg' {
144
+ interface SvgProps {
145
+ className?: string
146
+ }
109
147
  }
package/uniwind.css CHANGED
@@ -254,9 +254,4 @@
254
254
  }
255
255
 
256
256
  @custom-variant light (&:where(.light, .light *));
257
- @custom-variant dark (&:where(.dark, .dark *));
258
- @custom-variant premium (&:where(.premium, .premium *));
259
-
260
- @theme {
261
- --color-background: unset;
262
- }
257
+ @custom-variant dark (&:where(.dark, .dark *));