@react-native-styled-system/core 1.4.4 → 2.1.1

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 (127) hide show
  1. package/lib/commonjs/@types/Responsive.js +8 -0
  2. package/lib/commonjs/@types/Responsive.js.map +1 -0
  3. package/lib/commonjs/@types/SxProps.js +9 -0
  4. package/lib/commonjs/@types/SxProps.js.map +1 -1
  5. package/lib/commonjs/@types/ThemedDict.js +396 -2
  6. package/lib/commonjs/@types/ThemedDict.js.map +1 -1
  7. package/lib/commonjs/__testUtils__/testTheme.js +51 -0
  8. package/lib/commonjs/__testUtils__/testTheme.js.map +1 -0
  9. package/lib/commonjs/hook/useSx.js +13 -4
  10. package/lib/commonjs/hook/useSx.js.map +1 -1
  11. package/lib/commonjs/hook/useSxStyle.js +10 -3
  12. package/lib/commonjs/hook/useSxStyle.js.map +1 -1
  13. package/lib/commonjs/index.js +22 -0
  14. package/lib/commonjs/index.js.map +1 -1
  15. package/lib/commonjs/internal/util/resolveResponsiveValue.js +52 -0
  16. package/lib/commonjs/internal/util/resolveResponsiveValue.js.map +1 -0
  17. package/lib/commonjs/provider/StyledSystemProvider.js +17 -11
  18. package/lib/commonjs/provider/StyledSystemProvider.js.map +1 -1
  19. package/lib/commonjs/util/createSxComponent.js +5 -7
  20. package/lib/commonjs/util/createSxComponent.js.map +1 -1
  21. package/lib/commonjs/util/createTheme.js +43 -0
  22. package/lib/commonjs/util/createTheme.js.map +1 -0
  23. package/lib/commonjs/util/propsToThemedStyle.js +11 -3
  24. package/lib/commonjs/util/propsToThemedStyle.js.map +1 -1
  25. package/lib/module/@types/AnyStyle.js +0 -2
  26. package/lib/module/@types/Responsive.js +2 -0
  27. package/lib/module/@types/Responsive.js.map +1 -0
  28. package/lib/module/@types/SxProps.js +9 -2
  29. package/lib/module/@types/SxProps.js.map +1 -1
  30. package/lib/module/@types/ThemedDict.js +394 -3
  31. package/lib/module/@types/ThemedDict.js.map +1 -1
  32. package/lib/module/@types/ThemedTypings.js +0 -2
  33. package/lib/module/@types/Token.js +0 -2
  34. package/lib/module/__testUtils__/testTheme.js +45 -0
  35. package/lib/module/__testUtils__/testTheme.js.map +1 -0
  36. package/lib/module/hook/useSx.js +13 -6
  37. package/lib/module/hook/useSx.js.map +1 -1
  38. package/lib/module/hook/useSxStyle.js +10 -5
  39. package/lib/module/hook/useSxStyle.js.map +1 -1
  40. package/lib/module/hook/useSxTokens.js +0 -2
  41. package/lib/module/hook/useSxTokens.js.map +1 -1
  42. package/lib/module/index.js +2 -2
  43. package/lib/module/index.js.map +1 -1
  44. package/lib/module/internal/TokenParser/ColorsParser.js +0 -2
  45. package/lib/module/internal/TokenParser/ColorsParser.js.map +1 -1
  46. package/lib/module/internal/TokenParser/RadiiParser.js +0 -2
  47. package/lib/module/internal/TokenParser/RadiiParser.js.map +1 -1
  48. package/lib/module/internal/TokenParser/SizesParser.js +0 -2
  49. package/lib/module/internal/TokenParser/SizesParser.js.map +1 -1
  50. package/lib/module/internal/TokenParser/SpaceParser.js +0 -2
  51. package/lib/module/internal/TokenParser/SpaceParser.js.map +1 -1
  52. package/lib/module/internal/TokenParser/TokenParser.js +0 -2
  53. package/lib/module/internal/TokenParser/TokenParser.js.map +1 -1
  54. package/lib/module/internal/TokenParser/TypographyParser.js +0 -2
  55. package/lib/module/internal/TokenParser/TypographyParser.js.map +1 -1
  56. package/lib/module/internal/useStableCallback.js +0 -2
  57. package/lib/module/internal/useStableCallback.js.map +1 -1
  58. package/lib/module/internal/util/StyleHash.js +0 -2
  59. package/lib/module/internal/util/StyleHash.js.map +1 -1
  60. package/lib/module/internal/util/fillStyleIfNotNullish.js +0 -2
  61. package/lib/module/internal/util/fillStyleIfNotNullish.js.map +1 -1
  62. package/lib/module/internal/util/mutateShortcutPropToOriginalKeys.js +0 -2
  63. package/lib/module/internal/util/mutateShortcutPropToOriginalKeys.js.map +1 -1
  64. package/lib/module/internal/util/parsePxSuffixNumber.js +0 -2
  65. package/lib/module/internal/util/parsePxSuffixNumber.js.map +1 -1
  66. package/lib/module/internal/util/printWarning.js +0 -2
  67. package/lib/module/internal/util/printWarning.js.map +1 -1
  68. package/lib/module/internal/util/resolveResponsiveValue.js +44 -0
  69. package/lib/module/internal/util/resolveResponsiveValue.js.map +1 -0
  70. package/lib/module/provider/StyledSystemProvider.js +17 -12
  71. package/lib/module/provider/StyledSystemProvider.js.map +1 -1
  72. package/lib/module/util/createSxComponent.js +5 -9
  73. package/lib/module/util/createSxComponent.js.map +1 -1
  74. package/lib/module/util/createTheme.js +37 -0
  75. package/lib/module/util/createTheme.js.map +1 -0
  76. package/lib/module/util/propsToThemedStyle.js +11 -5
  77. package/lib/module/util/propsToThemedStyle.js.map +1 -1
  78. package/lib/typescript/src/@types/Responsive.d.ts +4 -0
  79. package/lib/typescript/src/@types/Responsive.d.ts.map +1 -0
  80. package/lib/typescript/src/@types/SxProps.d.ts +15 -3
  81. package/lib/typescript/src/@types/SxProps.d.ts.map +1 -1
  82. package/lib/typescript/src/@types/ThemedDict.d.ts +26 -0
  83. package/lib/typescript/src/@types/ThemedDict.d.ts.map +1 -1
  84. package/lib/typescript/src/__testUtils__/testTheme.d.ts +12 -0
  85. package/lib/typescript/src/__testUtils__/testTheme.d.ts.map +1 -0
  86. package/lib/typescript/src/hook/useSx.d.ts +2 -1
  87. package/lib/typescript/src/hook/useSx.d.ts.map +1 -1
  88. package/lib/typescript/src/hook/useSxStyle.d.ts +2 -1
  89. package/lib/typescript/src/hook/useSxStyle.d.ts.map +1 -1
  90. package/lib/typescript/src/index.d.ts +2 -0
  91. package/lib/typescript/src/index.d.ts.map +1 -1
  92. package/lib/typescript/src/internal/util/resolveResponsiveValue.d.ts +12 -0
  93. package/lib/typescript/src/internal/util/resolveResponsiveValue.d.ts.map +1 -0
  94. package/lib/typescript/src/provider/StyledSystemProvider.d.ts +3 -1
  95. package/lib/typescript/src/provider/StyledSystemProvider.d.ts.map +1 -1
  96. package/lib/typescript/src/util/createSxComponent.d.ts +4 -4
  97. package/lib/typescript/src/util/createSxComponent.d.ts.map +1 -1
  98. package/lib/typescript/src/util/createTheme.d.ts +4 -0
  99. package/lib/typescript/src/util/createTheme.d.ts.map +1 -0
  100. package/lib/typescript/src/util/propsToThemedStyle.d.ts +3 -1
  101. package/lib/typescript/src/util/propsToThemedStyle.d.ts.map +1 -1
  102. package/package.json +9 -8
  103. package/src/@types/Responsive.ts +7 -0
  104. package/src/@types/SxProps.ts +36 -7
  105. package/src/@types/ThemedDict.ts +412 -0
  106. package/src/__testUtils__/testTheme.ts +43 -0
  107. package/src/hook/useSx.test.ts +117 -38
  108. package/src/hook/useSx.ts +11 -2
  109. package/src/hook/useSxStyle.test.ts +102 -33
  110. package/src/hook/useSxStyle.ts +12 -1
  111. package/src/hook/useSxTokens.test.ts +65 -32
  112. package/src/index.ts +2 -0
  113. package/src/internal/util/resolveResponsiveValue.test.ts +171 -0
  114. package/src/internal/util/resolveResponsiveValue.ts +58 -0
  115. package/src/provider/StyledSystemProvider.tsx +14 -4
  116. package/src/util/createSxComponent.tsx +8 -4
  117. package/src/util/createTheme.test.ts +126 -0
  118. package/src/util/createTheme.ts +29 -0
  119. package/src/util/propsToThemedStyle.ts +10 -3
  120. package/lib/commonjs/internal/util/fillNullishThemeKey.js +0 -18
  121. package/lib/commonjs/internal/util/fillNullishThemeKey.js.map +0 -1
  122. package/lib/commonjs/package.json +0 -1
  123. package/lib/module/internal/util/fillNullishThemeKey.js +0 -13
  124. package/lib/module/internal/util/fillNullishThemeKey.js.map +0 -1
  125. package/lib/typescript/src/internal/util/fillNullishThemeKey.d.ts +0 -3
  126. package/lib/typescript/src/internal/util/fillNullishThemeKey.d.ts.map +0 -1
  127. package/src/internal/util/fillNullishThemeKey.ts +0 -12
@@ -9,6 +9,7 @@ export interface ThemedDict {
9
9
  colors: Record<string | number, ColorsValue>;
10
10
  radii: Record<string | number, RadiiValue>;
11
11
  typography: Record<string | number, TypographyValue>;
12
+ breakpoints?: number[];
12
13
  }
13
14
  export const emptyThemedDict = {
14
15
  space: {},
@@ -16,4 +17,415 @@ export const emptyThemedDict = {
16
17
  sizes: {},
17
18
  radii: {},
18
19
  typography: {},
20
+ breakpoints: [],
21
+ } satisfies ThemedDict;
22
+
23
+ const defaultSpace: Record<string, SpaceValue> = {
24
+ '0': 0,
25
+ 'px': 1,
26
+ '0.5': 2,
27
+ '1': 4,
28
+ '2': 8,
29
+ '3': 12,
30
+ '4': 16,
31
+ '5': 20,
32
+ '6': 24,
33
+ '7': 28,
34
+ '8': 32,
35
+ '9': 36,
36
+ '10': 40,
37
+ '12': 48,
38
+ '14': 56,
39
+ '16': 64,
40
+ '20': 80,
41
+ '24': 96,
42
+ '32': 128,
43
+ '40': 160,
44
+ '48': 192,
45
+ };
46
+
47
+ const defaultColors: Record<string, ColorsValue> = {
48
+ 'white': '#FFFFFF',
49
+ 'black': '#000000',
50
+ 'transparent': 'transparent',
51
+
52
+ 'slate.50': '#f8fafc',
53
+ 'slate.100': '#f1f5f9',
54
+ 'slate.200': '#e2e8f0',
55
+ 'slate.300': '#cad5e2',
56
+ 'slate.400': '#90a1b9',
57
+ 'slate.500': '#62748e',
58
+ 'slate.600': '#45556c',
59
+ 'slate.700': '#314158',
60
+ 'slate.800': '#1d293d',
61
+ 'slate.900': '#0f172b',
62
+ 'slate.950': '#020618',
63
+
64
+ 'gray.50': '#f9fafb',
65
+ 'gray.100': '#f3f4f6',
66
+ 'gray.200': '#e5e7eb',
67
+ 'gray.300': '#d1d5dc',
68
+ 'gray.400': '#99a1af',
69
+ 'gray.500': '#6a7282',
70
+ 'gray.600': '#4a5565',
71
+ 'gray.700': '#364153',
72
+ 'gray.800': '#1e2939',
73
+ 'gray.900': '#101828',
74
+ 'gray.950': '#030712',
75
+
76
+ 'zinc.50': '#fafafa',
77
+ 'zinc.100': '#f4f4f5',
78
+ 'zinc.200': '#e4e4e7',
79
+ 'zinc.300': '#d4d4d8',
80
+ 'zinc.400': '#9f9fa9',
81
+ 'zinc.500': '#71717b',
82
+ 'zinc.600': '#52525c',
83
+ 'zinc.700': '#3f3f46',
84
+ 'zinc.800': '#27272a',
85
+ 'zinc.900': '#18181b',
86
+ 'zinc.950': '#09090b',
87
+
88
+ 'neutral.50': '#fafafa',
89
+ 'neutral.100': '#f5f5f5',
90
+ 'neutral.200': '#e5e5e5',
91
+ 'neutral.300': '#d4d4d4',
92
+ 'neutral.400': '#a1a1a1',
93
+ 'neutral.500': '#737373',
94
+ 'neutral.600': '#525252',
95
+ 'neutral.700': '#404040',
96
+ 'neutral.800': '#262626',
97
+ 'neutral.900': '#171717',
98
+ 'neutral.950': '#0a0a0a',
99
+
100
+ 'stone.50': '#fafaf9',
101
+ 'stone.100': '#f5f5f4',
102
+ 'stone.200': '#e7e5e4',
103
+ 'stone.300': '#d7d3d1',
104
+ 'stone.400': '#a6a09b',
105
+ 'stone.500': '#79716b',
106
+ 'stone.600': '#57534d',
107
+ 'stone.700': '#44403b',
108
+ 'stone.800': '#292524',
109
+ 'stone.900': '#1c1917',
110
+ 'stone.950': '#0c0a09',
111
+
112
+ 'red.50': '#fef2f2',
113
+ 'red.100': '#ffe2e2',
114
+ 'red.200': '#ffc9c9',
115
+ 'red.300': '#ffa2a2',
116
+ 'red.400': '#ff6467',
117
+ 'red.500': '#fb2c36',
118
+ 'red.600': '#e7000b',
119
+ 'red.700': '#c10007',
120
+ 'red.800': '#9f0712',
121
+ 'red.900': '#82181a',
122
+ 'red.950': '#460809',
123
+
124
+ 'orange.50': '#fff7ed',
125
+ 'orange.100': '#ffedd4',
126
+ 'orange.200': '#ffd6a7',
127
+ 'orange.300': '#ffb869',
128
+ 'orange.400': '#ff8903',
129
+ 'orange.500': '#ff6900',
130
+ 'orange.600': '#f54900',
131
+ 'orange.700': '#ca3500',
132
+ 'orange.800': '#9f2d00',
133
+ 'orange.900': '#7e2a0c',
134
+ 'orange.950': '#441306',
135
+
136
+ 'amber.50': '#fffbeb',
137
+ 'amber.100': '#fef3c6',
138
+ 'amber.200': '#fee685',
139
+ 'amber.300': '#ffd230',
140
+ 'amber.400': '#ffb900',
141
+ 'amber.500': '#fe9a00',
142
+ 'amber.600': '#e17100',
143
+ 'amber.700': '#bb4d00',
144
+ 'amber.800': '#973c00',
145
+ 'amber.900': '#7b3306',
146
+ 'amber.950': '#461901',
147
+
148
+ 'yellow.50': '#fefce8',
149
+ 'yellow.100': '#fef9c2',
150
+ 'yellow.200': '#fff085',
151
+ 'yellow.300': '#ffdf20',
152
+ 'yellow.400': '#fdc700',
153
+ 'yellow.500': '#f0b100',
154
+ 'yellow.600': '#d08700',
155
+ 'yellow.700': '#a65f00',
156
+ 'yellow.800': '#894b00',
157
+ 'yellow.900': '#733e0a',
158
+ 'yellow.950': '#432004',
159
+
160
+ 'lime.50': '#f7fee7',
161
+ 'lime.100': '#ecfcca',
162
+ 'lime.200': '#d8f999',
163
+ 'lime.300': '#bbf451',
164
+ 'lime.400': '#9ae600',
165
+ 'lime.500': '#7ccf00',
166
+ 'lime.600': '#5ea500',
167
+ 'lime.700': '#497d00',
168
+ 'lime.800': '#3d6300',
169
+ 'lime.900': '#35530e',
170
+ 'lime.950': '#192e03',
171
+
172
+ 'green.50': '#f0fdf4',
173
+ 'green.100': '#dcfce7',
174
+ 'green.200': '#b9f8cf',
175
+ 'green.300': '#7bf1a7',
176
+ 'green.400': '#06df72',
177
+ 'green.500': '#00c950',
178
+ 'green.600': '#00a63e',
179
+ 'green.700': '#008235',
180
+ 'green.800': '#026630',
181
+ 'green.900': '#0d542b',
182
+ 'green.950': '#032e15',
183
+
184
+ 'emerald.50': '#ecfdf5',
185
+ 'emerald.100': '#d0fae5',
186
+ 'emerald.200': '#a4f4cf',
187
+ 'emerald.300': '#5ee9b5',
188
+ 'emerald.400': '#00d492',
189
+ 'emerald.500': '#00bc7d',
190
+ 'emerald.600': '#009966',
191
+ 'emerald.700': '#007a55',
192
+ 'emerald.800': '#006045',
193
+ 'emerald.900': '#004f3b',
194
+ 'emerald.950': '#002c22',
195
+
196
+ 'teal.50': '#f0fdfa',
197
+ 'teal.100': '#cbfbf1',
198
+ 'teal.200': '#96f7e4',
199
+ 'teal.300': '#46ecd4',
200
+ 'teal.400': '#00d5bd',
201
+ 'teal.500': '#00bba7',
202
+ 'teal.600': '#009689',
203
+ 'teal.700': '#00786f',
204
+ 'teal.800': '#005f5a',
205
+ 'teal.900': '#0b4f4a',
206
+ 'teal.950': '#022f2e',
207
+
208
+ 'cyan.50': '#ecfeff',
209
+ 'cyan.100': '#cefafe',
210
+ 'cyan.200': '#a2f4fd',
211
+ 'cyan.300': '#53eafd',
212
+ 'cyan.400': '#00d3f2',
213
+ 'cyan.500': '#00b8db',
214
+ 'cyan.600': '#0092b8',
215
+ 'cyan.700': '#007595',
216
+ 'cyan.800': '#005f78',
217
+ 'cyan.900': '#104e64',
218
+ 'cyan.950': '#053345',
219
+
220
+ 'sky.50': '#f0f9ff',
221
+ 'sky.100': '#dff2fe',
222
+ 'sky.200': '#b8e6fe',
223
+ 'sky.300': '#74d4ff',
224
+ 'sky.400': '#00bcff',
225
+ 'sky.500': '#00a6f4',
226
+ 'sky.600': '#0084d1',
227
+ 'sky.700': '#0069a8',
228
+ 'sky.800': '#00598a',
229
+ 'sky.900': '#024a70',
230
+ 'sky.950': '#052f4a',
231
+
232
+ 'blue.50': '#eff6ff',
233
+ 'blue.100': '#dbeafe',
234
+ 'blue.200': '#bedbff',
235
+ 'blue.300': '#8ec5ff',
236
+ 'blue.400': '#51a2ff',
237
+ 'blue.500': '#2b7fff',
238
+ 'blue.600': '#155dfb',
239
+ 'blue.700': '#1447e6',
240
+ 'blue.800': '#193cb8',
241
+ 'blue.900': '#1c398e',
242
+ 'blue.950': '#162556',
243
+
244
+ 'indigo.50': '#eef2ff',
245
+ 'indigo.100': '#e0e7ff',
246
+ 'indigo.200': '#c7d2ff',
247
+ 'indigo.300': '#a3b3ff',
248
+ 'indigo.400': '#7c86ff',
249
+ 'indigo.500': '#615fff',
250
+ 'indigo.600': '#4f39f6',
251
+ 'indigo.700': '#432dd7',
252
+ 'indigo.800': '#372aac',
253
+ 'indigo.900': '#312c85',
254
+ 'indigo.950': '#1e1a4d',
255
+
256
+ 'violet.50': '#f5f3ff',
257
+ 'violet.100': '#ede9fe',
258
+ 'violet.200': '#ddd6ff',
259
+ 'violet.300': '#c4b4ff',
260
+ 'violet.400': '#a684ff',
261
+ 'violet.500': '#8e51ff',
262
+ 'violet.600': '#7f22fe',
263
+ 'violet.700': '#7008e7',
264
+ 'violet.800': '#5d0ec0',
265
+ 'violet.900': '#4d179a',
266
+ 'violet.950': '#2f0d68',
267
+
268
+ 'purple.50': '#faf5ff',
269
+ 'purple.100': '#f3e8ff',
270
+ 'purple.200': '#e9d4ff',
271
+ 'purple.300': '#dab2ff',
272
+ 'purple.400': '#c27aff',
273
+ 'purple.500': '#ad46ff',
274
+ 'purple.600': '#9810fa',
275
+ 'purple.700': '#8200db',
276
+ 'purple.800': '#6e11b0',
277
+ 'purple.900': '#59168b',
278
+ 'purple.950': '#3c0366',
279
+
280
+ 'fuchsia.50': '#fdf4ff',
281
+ 'fuchsia.100': '#fae8ff',
282
+ 'fuchsia.200': '#f6cfff',
283
+ 'fuchsia.300': '#f4a8ff',
284
+ 'fuchsia.400': '#ed6aff',
285
+ 'fuchsia.500': '#e12afb',
286
+ 'fuchsia.600': '#c800de',
287
+ 'fuchsia.700': '#a800b7',
288
+ 'fuchsia.800': '#8a0194',
289
+ 'fuchsia.900': '#721378',
290
+ 'fuchsia.950': '#4b004f',
291
+
292
+ 'pink.50': '#fdf2f8',
293
+ 'pink.100': '#fce7f3',
294
+ 'pink.200': '#fccee8',
295
+ 'pink.300': '#fea5d5',
296
+ 'pink.400': '#fb64b6',
297
+ 'pink.500': '#f6339a',
298
+ 'pink.600': '#e60076',
299
+ 'pink.700': '#c6005b',
300
+ 'pink.800': '#a3004c',
301
+ 'pink.900': '#861043',
302
+ 'pink.950': '#510424',
303
+
304
+ 'rose.50': '#fff1f2',
305
+ 'rose.100': '#ffe4e6',
306
+ 'rose.200': '#ffccd2',
307
+ 'rose.300': '#ffa1ad',
308
+ 'rose.400': '#ff637e',
309
+ 'rose.500': '#ff2056',
310
+ 'rose.600': '#ec003f',
311
+ 'rose.700': '#c70036',
312
+ 'rose.800': '#a50036',
313
+ 'rose.900': '#8b0836',
314
+ 'rose.950': '#4d0218',
315
+ };
316
+
317
+ const defaultRadii: Record<string, RadiiValue> = {
318
+ 'none': 0,
319
+ 'sm': 4,
320
+ 'md': 8,
321
+ 'lg': 12,
322
+ 'xl': 16,
323
+ '2xl': 24,
324
+ 'full': 9999,
325
+ };
326
+
327
+ const defaultTypography: Record<string, TypographyValue> = {
328
+ h1: { fontSize: 32, fontWeight: 'bold', lineHeight: 40 },
329
+ h2: { fontSize: 24, fontWeight: 'bold', lineHeight: 32 },
330
+ h3: { fontSize: 20, fontWeight: '600', lineHeight: 28 },
331
+ body: { fontSize: 16, lineHeight: 24 },
332
+ caption: { fontSize: 14, lineHeight: 20 },
333
+ small: { fontSize: 12, lineHeight: 16 },
334
+ };
335
+
336
+ const grayScales = ['slate', 'gray', 'zinc', 'neutral', 'stone'] as const;
337
+
338
+ export type BaseColor = (typeof grayScales)[number];
339
+
340
+ export type ThemeColor =
341
+ | BaseColor
342
+ | 'red'
343
+ | 'orange'
344
+ | 'amber'
345
+ | 'yellow'
346
+ | 'lime'
347
+ | 'green'
348
+ | 'emerald'
349
+ | 'teal'
350
+ | 'cyan'
351
+ | 'sky'
352
+ | 'blue'
353
+ | 'indigo'
354
+ | 'violet'
355
+ | 'purple'
356
+ | 'fuchsia'
357
+ | 'pink'
358
+ | 'rose';
359
+
360
+ export const createThemeColors = ({ base, theme }: { base: BaseColor; theme: ThemeColor }) => {
361
+ const b = (shade: number) => defaultColors[`${base}.${shade}`]!;
362
+ const t = (shade: number) => defaultColors[`${theme}.${shade}`]!;
363
+ const isGray = (grayScales as readonly string[]).includes(theme);
364
+
365
+ const light: Record<string, ColorsValue> = {
366
+ 'background': '#FFFFFF',
367
+ 'foreground': b(950),
368
+ 'card': '#FFFFFF',
369
+ 'card-foreground': b(950),
370
+ 'popover': '#FFFFFF',
371
+ 'popover-foreground': b(950),
372
+ 'primary': isGray ? t(900) : t(600),
373
+ 'primary-foreground': isGray ? t(50) : '#FFFFFF',
374
+ 'secondary': b(100),
375
+ 'secondary-foreground': b(900),
376
+ 'muted': b(100),
377
+ 'muted-foreground': b(500),
378
+ 'accent': b(100),
379
+ 'accent-foreground': b(900),
380
+ 'destructive': defaultColors['red.600']!,
381
+ 'destructive-foreground': b(50),
382
+ 'border': b(200),
383
+ 'input': b(200),
384
+ 'ring': isGray ? b(400) : t(400),
385
+ 'chart-1': defaultColors['orange.600']!,
386
+ 'chart-2': defaultColors['teal.600']!,
387
+ 'chart-3': defaultColors['cyan.900']!,
388
+ 'chart-4': defaultColors['amber.400']!,
389
+ 'chart-5': defaultColors['amber.500']!,
390
+ };
391
+
392
+ const dark: Record<string, ColorsValue> = {
393
+ 'background': b(950),
394
+ 'foreground': b(50),
395
+ 'card': b(900),
396
+ 'card-foreground': b(50),
397
+ 'popover': b(900),
398
+ 'popover-foreground': b(50),
399
+ 'primary': isGray ? t(200) : t(500),
400
+ 'primary-foreground': isGray ? t(900) : '#FFFFFF',
401
+ 'secondary': b(800),
402
+ 'secondary-foreground': b(50),
403
+ 'muted': b(800),
404
+ 'muted-foreground': b(400),
405
+ 'accent': b(800),
406
+ 'accent-foreground': b(50),
407
+ 'destructive': defaultColors['red.400']!,
408
+ 'destructive-foreground': b(50),
409
+ 'border': b(800),
410
+ 'input': b(800),
411
+ 'ring': isGray ? b(500) : t(500),
412
+ 'chart-1': defaultColors['blue.700']!,
413
+ 'chart-2': defaultColors['emerald.500']!,
414
+ 'chart-3': defaultColors['amber.500']!,
415
+ 'chart-4': defaultColors['purple.500']!,
416
+ 'chart-5': defaultColors['rose.500']!,
417
+ };
418
+
419
+ return { light, dark };
420
+ };
421
+
422
+ const defaultSemanticColors = createThemeColors({ base: 'neutral', theme: 'neutral' });
423
+
424
+ export const defaultTheme = {
425
+ space: defaultSpace,
426
+ sizes: { ...defaultSpace, full: '100%' as const, half: '50%' as const },
427
+ colors: { ...defaultColors, ...defaultSemanticColors.light },
428
+ radii: defaultRadii,
429
+ typography: defaultTypography,
430
+ breakpoints: [480, 768, 1024],
19
431
  } satisfies ThemedDict;
@@ -0,0 +1,43 @@
1
+ import type { ThemedDict } from '../@types/ThemedDict';
2
+ import { emptyThemedDict } from '../@types/ThemedDict';
3
+
4
+ export const emptyTheme = emptyThemedDict;
5
+
6
+ export const baseTheme: ThemedDict = {
7
+ colors: {
8
+ red: 'red',
9
+ blue: 'blue',
10
+ green: 'green',
11
+ },
12
+ sizes: {
13
+ 1: 4,
14
+ 2: 8,
15
+ pagePadding: 20,
16
+ full: '100%',
17
+ },
18
+ space: { 1: 4, 2: 8, pagePadding: 20, full: '100%' },
19
+ radii: {
20
+ sm: 8,
21
+ md: 12,
22
+ lg: 20,
23
+ },
24
+ typography: {
25
+ title: {
26
+ fontFamily: 'Noto Sans',
27
+ fontSize: 14,
28
+ fontStyle: 'normal',
29
+ fontWeight: '400',
30
+ },
31
+ body: {
32
+ fontFamily: 'Noto Sans',
33
+ fontSize: 12,
34
+ fontStyle: 'normal',
35
+ fontWeight: '400',
36
+ },
37
+ },
38
+ };
39
+
40
+ export const responsiveTheme: ThemedDict = {
41
+ ...baseTheme,
42
+ breakpoints: [480, 768, 1024],
43
+ };
@@ -3,9 +3,9 @@ import { StyleSheet } from 'react-native';
3
3
  import { is } from '@mj-studio/js-util';
4
4
  import { renderHook } from '@testing-library/react-native';
5
5
 
6
+ import { baseTheme, emptyTheme, responsiveTheme } from '../__testUtils__/testTheme';
6
7
  import type { TextSxProps } from '../@types/SxProps';
7
8
  import type { ThemedDict } from '../@types/ThemedDict';
8
- import { emptyThemedDict } from '../@types/ThemedDict';
9
9
  import type { ThemedStyleType } from '../util/propsToThemedStyle';
10
10
 
11
11
  import type { StyleFallback, StyleTransform } from './useSx';
@@ -21,6 +21,7 @@ function expectResult(
21
21
  transform,
22
22
  fallback,
23
23
  cache,
24
+ screenWidth,
24
25
  }: {
25
26
  expectation: object;
26
27
  filteredPropsExpectation?: object;
@@ -28,13 +29,14 @@ function expectResult(
28
29
  transform?: StyleTransform;
29
30
  fallback?: StyleFallback;
30
31
  cache?: boolean;
32
+ screenWidth?: number;
31
33
  },
32
34
  ) {
33
35
  const {
34
36
  result: {
35
37
  current: { getStyle, filteredProps },
36
38
  },
37
- } = renderHook(() => useSx(props, { theme, styleType, transform, fallback, cache }));
39
+ } = renderHook(() => useSx(props, { theme, styleType, transform, fallback, cache, screenWidth }));
38
40
 
39
41
  if (expectation) {
40
42
  expect(StyleSheet.flatten(getStyle())).toEqual(expectation);
@@ -47,42 +49,6 @@ function expectResult(
47
49
  return [getStyle(), filteredProps];
48
50
  }
49
51
 
50
- const emptyTheme = emptyThemedDict;
51
-
52
- const baseTheme: ThemedDict = {
53
- colors: {
54
- red: 'red',
55
- blue: 'blue',
56
- green: 'green',
57
- },
58
- sizes: {
59
- 1: 4,
60
- 2: 8,
61
- pagePadding: 20,
62
- full: '100%',
63
- },
64
- space: { 1: 4, 2: 8, pagePadding: 20, full: '100%' },
65
- radii: {
66
- sm: 8,
67
- md: 12,
68
- lg: 20,
69
- },
70
- typography: {
71
- title: {
72
- fontFamily: 'Noto Sans',
73
- fontSize: 14,
74
- fontStyle: 'normal',
75
- fontWeight: '400',
76
- },
77
- body: {
78
- fontFamily: 'Noto Sans',
79
- fontSize: 12,
80
- fontStyle: 'normal',
81
- fontWeight: '400',
82
- },
83
- },
84
- };
85
-
86
52
  describe('simple usages', () => {
87
53
  it('handle empty', () => {
88
54
  expectResult(baseTheme, {}, { expectation: {} });
@@ -404,3 +370,116 @@ describe('cache', () => {
404
370
  expect(style1 === style2).toBe(true);
405
371
  });
406
372
  });
373
+
374
+ describe('responsive', () => {
375
+ it.each([
376
+ { label: 'base', screenWidth: 320, expected: 100 },
377
+ { label: 'first breakpoint', screenWidth: 480, expected: 200 },
378
+ { label: 'second breakpoint', screenWidth: 768, expected: 300 },
379
+ { label: 'third breakpoint', screenWidth: 1024, expected: 400 },
380
+ ])('resolves responsive array based on screenWidth - $label', ({ screenWidth, expected }) => {
381
+ expectResult(
382
+ responsiveTheme,
383
+ { w: [100, 200, 300, 400] as any },
384
+ { expectation: { width: expected }, screenWidth },
385
+ );
386
+ });
387
+
388
+ it('handles mixed array and single values', () => {
389
+ expectResult(
390
+ responsiveTheme,
391
+ { w: [100, 200] as any, h: 50 },
392
+ { expectation: { width: 200, height: 50 }, screenWidth: 500 },
393
+ );
394
+ });
395
+
396
+ it('resolves color token arrays', () => {
397
+ expectResult(
398
+ responsiveTheme,
399
+ { bg: ['red', 'blue'] as any },
400
+ { expectation: { backgroundColor: 'blue' }, screenWidth: 500 },
401
+ );
402
+ });
403
+
404
+ it('uses base value when no breakpoints defined', () => {
405
+ expectResult(
406
+ baseTheme,
407
+ { w: [100, 200, 300] as any },
408
+ { expectation: { width: 100 }, screenWidth: 9999 },
409
+ );
410
+ });
411
+
412
+ it('uses base value when screenWidth is 0 (default)', () => {
413
+ expectResult(
414
+ responsiveTheme,
415
+ { w: [100, 200] as any },
416
+ { expectation: { width: 100 }, screenWidth: 0 },
417
+ );
418
+ });
419
+
420
+ it('resolves space token arrays', () => {
421
+ expectResult(
422
+ responsiveTheme,
423
+ { m: [1, 2] as any },
424
+ { expectation: { margin: 8 }, screenWidth: 500 },
425
+ );
426
+ });
427
+
428
+ it('works with transform + responsive', () => {
429
+ expectResult(
430
+ responsiveTheme,
431
+ { mt: [1, 2] as any },
432
+ {
433
+ expectation: { marginTop: 8, marginHorizontal: 8 },
434
+ screenWidth: 500,
435
+ transform: ({ marginTop }) => ({
436
+ mx: is.number(marginTop) ? marginTop : 0,
437
+ }),
438
+ },
439
+ );
440
+ });
441
+
442
+ it('resolves responsive values in sx prop', () => {
443
+ expectResult(
444
+ responsiveTheme,
445
+ { sx: { w: [100, 200] as any } },
446
+ { expectation: { width: 200 }, screenWidth: 500 },
447
+ );
448
+ });
449
+
450
+ it('resolves responsive values in fallback', () => {
451
+ expectResult(
452
+ responsiveTheme,
453
+ {},
454
+ { fallback: { w: [100, 200] as any }, expectation: { width: 200 }, screenWidth: 500 },
455
+ );
456
+ });
457
+
458
+ it('resolves responsive radii token arrays', () => {
459
+ expectResult(
460
+ responsiveTheme,
461
+ { radius: ['sm', 'lg'] as any },
462
+ { expectation: { borderRadius: 20 }, screenWidth: 500 },
463
+ );
464
+ });
465
+
466
+ it('prop responsive overrides fallback responsive', () => {
467
+ expectResult(
468
+ responsiveTheme,
469
+ { w: [300, 400] as any },
470
+ {
471
+ fallback: { w: [100, 200] as any },
472
+ expectation: { width: 400 },
473
+ screenWidth: 500,
474
+ },
475
+ );
476
+ });
477
+
478
+ it('sx responsive overrides prop responsive', () => {
479
+ expectResult(
480
+ responsiveTheme,
481
+ { w: [100, 200] as any, sx: { w: [300, 400] as any } },
482
+ { expectation: { width: 400 }, screenWidth: 500 },
483
+ );
484
+ });
485
+ });
package/src/hook/useSx.ts CHANGED
@@ -25,6 +25,7 @@ export type UseSxOptions = {
25
25
  transform?: StyleTransform;
26
26
  fallback?: StyleFallback;
27
27
  cache?: boolean;
28
+ screenWidth?: number;
28
29
  };
29
30
  const defaultUseSxOptions: UseSxOptions = { styleType: 'ViewStyle' };
30
31
  export const useSx = <P extends Props = Props>(
@@ -35,6 +36,7 @@ export const useSx = <P extends Props = Props>(
35
36
  transform = defaultUseSxOptions.transform,
36
37
  fallback,
37
38
  cache,
39
+ screenWidth: optionScreenWidth,
38
40
  }: UseSxOptions = defaultUseSxOptions,
39
41
  ) => {
40
42
  const styledSystemContext = useContext(StyledSystemContext);
@@ -42,10 +44,12 @@ export const useSx = <P extends Props = Props>(
42
44
  const getStyle = useStableCallback((): StyleProp<AnyStyle> | undefined => {
43
45
  const skip = !props && !fallback;
44
46
  const theme = optionTheme ?? styledSystemContext?.theme;
47
+ const breakpoints = theme?.breakpoints ?? [];
48
+ const screenWidth = optionScreenWidth ?? styledSystemContext?.screenWidth ?? 0;
45
49
 
46
50
  if (skip) {
47
51
  if (is.function(transform)) {
48
- return propsToThemedStyle({ theme, sx: transform({}) });
52
+ return propsToThemedStyle({ theme, sx: transform({}), breakpoints, screenWidth });
49
53
  } else {
50
54
  return;
51
55
  }
@@ -68,6 +72,8 @@ export const useSx = <P extends Props = Props>(
68
72
  theme,
69
73
  sx: mergedSx,
70
74
  styleType,
75
+ breakpoints,
76
+ screenWidth,
71
77
  });
72
78
 
73
79
  const composedStyle = !mergedSxStyle
@@ -79,7 +85,10 @@ export const useSx = <P extends Props = Props>(
79
85
  if (is.function(transform)) {
80
86
  const transformedSx = transform(StyleSheet.flatten(composedStyle));
81
87
 
82
- const ret = [composedStyle, propsToThemedStyle({ theme, sx: transformedSx, styleType })];
88
+ const ret = [
89
+ composedStyle,
90
+ propsToThemedStyle({ theme, sx: transformedSx, styleType, breakpoints, screenWidth }),
91
+ ];
83
92
 
84
93
  if (cache) {
85
94
  return getCachedStyle(ret);