1import { lightTheme, darkTheme, shadows } from '@expo/styleguide-native';
2import { View as RNView, StyleSheet } from 'react-native';
3
4import { create } from './create-primitive';
5import {
6  scale,
7  padding,
8  margin,
9  rounded,
10  bg,
11  bgDark,
12  width,
13  height,
14  borderDark,
15  border,
16} from './theme';
17
18export const View = create(RNView, {
19  variants: {
20    overflow: {
21      hidden: {
22        overflow: 'hidden',
23      },
24    },
25
26    align: {
27      centered: {
28        justifyContent: 'center',
29        alignItems: 'center',
30      },
31      start: {
32        alignItems: 'flex-start',
33      },
34    },
35
36    flex: {
37      '1': { flex: 1 },
38      '0': { flex: 0 },
39    },
40
41    shrink: {
42      '1': { flexShrink: 1 },
43      '0': { flexShrink: 0 },
44    },
45
46    grow: {
47      '1': { flexGrow: 1 },
48      '0': { flexGrow: 0 },
49    },
50
51    bg,
52
53    opacity: {
54      '1': { opacity: 1 },
55      '0.5': { opacity: 0.5 },
56      '0.75': { opacity: 0.75 },
57      '0': { opacity: 0 },
58    },
59
60    inset: {
61      top: {
62        position: 'absolute',
63        top: 0,
64        left: 0,
65        right: 0,
66      },
67
68      bottom: {
69        position: 'absolute',
70        bottom: 0,
71        left: 0,
72        right: 0,
73      },
74
75      full: {
76        position: 'absolute',
77        top: 0,
78        left: 0,
79        right: 0,
80        bottom: 0,
81      },
82    },
83
84    border: {
85      default: { borderColor: lightTheme.border.default, borderWidth: 1 },
86      hairline: { borderColor: lightTheme.border.default, borderWidth: StyleSheet.hairlineWidth },
87      warning: { borderColor: lightTheme.border.warning, borderWidth: 1 },
88      error: { borderColor: lightTheme.border.error, borderWidth: 1 },
89    },
90
91    ...rounded,
92
93    shadow: {
94      micro: shadows.micro,
95      tiny: shadows.tiny,
96      small: shadows.small,
97      medium: shadows.medium,
98      button: shadows.button,
99    },
100
101    width,
102    height,
103
104    ...padding,
105    ...margin,
106  },
107
108  selectors: {
109    dark: {
110      bg: bgDark,
111
112      border: borderDark,
113    },
114
115    light: {
116      bg: {},
117    },
118  },
119});
120
121export const Row = create(RNView, {
122  base: {
123    flexDirection: 'row',
124  },
125
126  variants: {
127    bg,
128
129    flex: {
130      '1': { flex: 1 },
131      '0': { flex: 0 },
132    },
133
134    shrink: {
135      '1': { flexShrink: 1 },
136      '0': { flexShrink: 0 },
137    },
138
139    grow: {
140      '1': { flexGrow: 1 },
141      '0': { flexGrow: 0 },
142    },
143
144    align: {
145      center: { alignItems: 'center' },
146      start: { alignItems: 'flex-start' },
147      end: { alignItems: 'flex-end' },
148    },
149
150    justify: {
151      center: { justifyContent: 'center' },
152      start: { justifyContent: 'flex-start' },
153      end: { justifyContent: 'flex-end' },
154      between: { justifyContent: 'space-between' },
155      around: { justifyContent: 'space-around' },
156    },
157
158    ...padding,
159    ...margin,
160
161    ...rounded,
162
163    border,
164  },
165
166  selectors: {
167    dark: {
168      bg: bgDark,
169      border: borderDark,
170    },
171  },
172});
173
174const Horizontal = create(RNView, {
175  base: {
176    flex: 1,
177  },
178  variants: {
179    bg,
180    size: {
181      micro: { width: scale.micro, flex: 0 },
182      tiny: { width: scale.tiny, flex: 0 },
183      small: { width: scale.small, flex: 0 },
184      medium: { width: scale.medium, flex: 0 },
185      large: { width: scale.large, flex: 0 },
186      xl: { width: scale.xl, flex: 0 },
187    },
188  },
189
190  selectors: {
191    dark: {
192      bg: bgDark,
193    },
194  },
195});
196
197const Vertical = create(RNView, {
198  base: {
199    flex: 1,
200  },
201  variants: {
202    bg,
203    size: {
204      micro: { height: scale.micro, flex: 0 },
205      tiny: { height: scale.tiny, flex: 0 },
206      small: { height: scale.small, flex: 0 },
207      medium: { height: scale.medium, flex: 0 },
208      large: { height: scale.large, flex: 0 },
209      xl: { height: scale.xl, flex: 0 },
210    },
211  },
212
213  selectors: {
214    dark: {
215      bg: bgDark,
216    },
217  },
218});
219
220export const Spacer = {
221  Vertical,
222  Horizontal,
223};
224
225export const Divider = create(RNView, {
226  base: {
227    height: StyleSheet.hairlineWidth,
228    backgroundColor: lightTheme.border.default,
229  },
230
231  variants: {
232    weight: {
233      thin: { height: StyleSheet.hairlineWidth },
234      normal: { height: 1 },
235      heavy: { height: 2 },
236    },
237
238    ...margin,
239  },
240
241  selectors: {
242    dark: {
243      base: {
244        height: StyleSheet.hairlineWidth,
245        backgroundColor: darkTheme.border.default,
246      },
247    },
248  },
249});
250
251export const StatusIndicator = create(RNView, {
252  base: {
253    backgroundColor: lightTheme.status.default,
254    borderRadius: 9999,
255  },
256
257  variants: {
258    status: {
259      info: { backgroundColor: lightTheme.status.info },
260      success: { backgroundColor: lightTheme.status.success },
261      warning: { backgroundColor: lightTheme.status.warning },
262      error: { backgroundColor: lightTheme.status.error },
263      default: { backgroundColor: lightTheme.status.default },
264    },
265
266    size: {
267      small: {
268        width: scale.small,
269        height: scale.small,
270      },
271      medium: {
272        width: scale.medium,
273        height: scale.medium,
274      },
275    },
276  },
277
278  selectors: {
279    dark: {
280      info: { backgroundColor: darkTheme.status.info },
281      success: { backgroundColor: darkTheme.status.success },
282      warning: { backgroundColor: darkTheme.status.warning },
283      error: { backgroundColor: darkTheme.status.error },
284      default: { backgroundColor: darkTheme.status.default },
285    },
286  },
287});
288