1import { spacing, lightTheme, darkTheme, borderRadius, typography } from '@expo/styleguide-native';
2import { TextStyle, Platform, StyleSheet } from 'react-native';
3
4type SpacingKey = `${keyof typeof spacing}`;
5type DescriptiveScale = 'micro' | 'tiny' | 'small' | 'medium' | 'large' | 'xl';
6type ScaleKey = SpacingKey | DescriptiveScale;
7type Scale = Record<ScaleKey, number>;
8
9export const scale: Scale = {
10  micro: spacing[0.5],
11  tiny: spacing[1],
12  small: spacing[3],
13  medium: spacing[4],
14  large: spacing[6],
15  xl: spacing[8],
16  ...spacing,
17};
18
19function fullSpacingScaleForAttributes(attributes: string[]) {
20  const obj: { [scaleKey: string]: any } = {};
21
22  Object.keys(scale).forEach((key) => {
23    key = `${key}`;
24    const value: { [attribute: string]: number } = {};
25
26    attributes.forEach((attribute) => {
27      value[attribute] = scale[key as ScaleKey];
28    });
29
30    obj[key] = value;
31  });
32
33  return obj as Record<SpacingKey | DescriptiveScale, any>;
34}
35
36export const padding = {
37  padding: fullSpacingScaleForAttributes(['padding']),
38  px: fullSpacingScaleForAttributes(['paddingHorizontal']),
39  py: fullSpacingScaleForAttributes(['paddingVertical']),
40  pb: fullSpacingScaleForAttributes(['paddingBottom']),
41  pt: fullSpacingScaleForAttributes(['paddingTop']),
42};
43
44export const margin = {
45  margin: fullSpacingScaleForAttributes(['margin']),
46  mx: fullSpacingScaleForAttributes(['marginHorizontal']),
47  my: fullSpacingScaleForAttributes(['marginVertical']),
48  mb: fullSpacingScaleForAttributes(['marginBottom']),
49  mt: fullSpacingScaleForAttributes(['marginTop']),
50};
51
52export const width = fullSpacingScaleForAttributes(['width']);
53export const height = fullSpacingScaleForAttributes(['height']);
54
55export const rounded = {
56  rounded: {
57    none: { borderRadius: 0 },
58    small: { borderRadius: borderRadius.small },
59    medium: { borderRadius: borderRadius.medium },
60    large: { borderRadius: borderRadius.large },
61    full: { borderRadius: 99999 },
62  },
63
64  roundedTop: {
65    none: { borderTopLeftRadius: 0, borderTopRightRadius: 0 },
66    small: { borderTopLeftRadius: borderRadius.small, borderTopRightRadius: borderRadius.small },
67    medium: {
68      borderTopLeftRadius: borderRadius.medium,
69      borderTopRightRadius: borderRadius.medium,
70    },
71    large: { borderTopLeftRadius: borderRadius.large, borderTopRightRadius: borderRadius.large },
72    full: { borderTopLeftRadius: 9999, borderTopRightRadius: 9999 },
73  },
74
75  roundedBottom: {
76    none: { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 },
77    small: {
78      borderBottomLeftRadius: borderRadius.small,
79      borderBottomRightRadius: borderRadius.small,
80    },
81    medium: {
82      borderBottomLeftRadius: borderRadius.medium,
83      borderBottomRightRadius: borderRadius.medium,
84    },
85    large: {
86      borderBottomLeftRadius: borderRadius.large,
87      borderBottomRightRadius: borderRadius.large,
88    },
89    full: { borderBottomLeftRadius: 9999, borderBottomRightRadius: 9999 },
90  },
91};
92
93export const text = {
94  align: {
95    center: { textAlign: 'center' as TextStyle['textAlign'] },
96  },
97
98  size: {
99    small: typography.fontSizes[12],
100    medium: typography.fontSizes[16],
101    large: typography.fontSizes[18],
102  },
103
104  leading: {
105    large: { lineHeight: 18 },
106  },
107
108  type: {
109    mono: {
110      fontFamily: Platform.OS === 'ios' ? 'Menlo' : 'monospace',
111    },
112    InterBlack: { fontFamily: 'Inter-Black' },
113    InterBlackItalic: { fontFamily: 'Inter-BlackItalic' },
114    InterBold: { fontFamily: 'Inter-Bold' },
115    InterBoldItalic: { fontFamily: 'Inter-BoldItalic' },
116    InterExtraBold: { fontFamily: 'Inter-ExtraBold' },
117    InterExtraBoldItalic: { fontFamily: 'Inter-ExtraBoldItalic' },
118    InterExtraLight: { fontFamily: 'Inter-ExtraLight' },
119    InterExtraLightItalic: { fontFamily: 'Inter-ExtraLightItalic' },
120    InterRegular: { fontFamily: 'Inter-Regular' },
121    InterItalic: { fontFamily: 'Inter-Italic' },
122    InterLight: { fontFamily: 'Inter-Light' },
123    InterLightItalic: { fontFamily: 'Inter-LightItalic' },
124    InterMedium: { fontFamily: 'Inter-Medium' },
125    InterMediumItalic: { fontFamily: 'Inter-MediumItalic' },
126    InterSemiBold: { fontFamily: 'Inter-SemiBold' },
127    InterSemiBoldItalic: { fontFamily: 'Inter-SemiBoldItalic' },
128    InterThin: { fontFamily: 'Inter-Thin' },
129    InterThinItalic: { fontFamily: 'Inter-ThinItalic' },
130  },
131
132  weight: {
133    thin: { fontFamily: 'Inter-Thin' },
134    extralight: { fontFamily: 'Inter-ExtraLight' },
135    light: { fontFamily: 'Inter-Light' },
136    normal: { fontFamily: 'Inter-Regular' },
137    medium: { fontFamily: 'Inter-Medium' },
138    semibold: { fontFamily: 'Inter-SemiBold' },
139    bold: { fontFamily: 'Inter-Bold' },
140    extrabold: { fontFamily: 'Inter-ExtraBold' },
141    black: { fontFamily: 'Inter-Black' },
142  },
143
144  color: {
145    default: { color: lightTheme.text.default },
146    error: { color: lightTheme.text.error },
147    warning: { color: lightTheme.text.warning },
148    success: { color: lightTheme.text.success },
149    secondary: { color: lightTheme.text.secondary },
150    primary: { color: lightTheme.button.primary.background },
151    link: { color: lightTheme.link.default },
152  },
153};
154
155export const textDark = {
156  base: {
157    color: darkTheme.text.default,
158  },
159
160  color: {
161    default: { color: darkTheme.text.default },
162    error: { color: darkTheme.text.error },
163    warning: { color: darkTheme.text.warning },
164    success: { color: darkTheme.text.success },
165    secondary: { color: darkTheme.text.secondary },
166    primary: { color: darkTheme.button.primary.background },
167    link: { color: darkTheme.link.default },
168  },
169};
170
171export const bg = {
172  none: { backgroundColor: 'transparent' },
173  default: { backgroundColor: lightTheme.background.default },
174  secondary: { backgroundColor: lightTheme.background.secondary },
175  overlay: { backgroundColor: lightTheme.background.overlay },
176  success: { backgroundColor: lightTheme.background.success },
177  warning: { backgroundColor: lightTheme.background.warning },
178  error: { backgroundColor: lightTheme.background.error },
179};
180
181export const bgDark = {
182  default: { backgroundColor: darkTheme.background.default },
183  secondary: { backgroundColor: darkTheme.background.secondary },
184  overlay: { backgroundColor: darkTheme.background.overlay },
185  success: { backgroundColor: darkTheme.background.success },
186  warning: { backgroundColor: darkTheme.background.warning },
187  error: { backgroundColor: darkTheme.background.error },
188};
189
190type NavigationTheme = {
191  dark: boolean;
192  colors: {
193    primary: string;
194    background: string;
195    card: string;
196    text: string;
197    border: string;
198    notification: string;
199  };
200};
201
202export const lightNavigationTheme: NavigationTheme = {
203  dark: false,
204  colors: {
205    primary: lightTheme.button.primary.background,
206    background: lightTheme.background.screen,
207    card: lightTheme.background.default,
208    text: lightTheme.text.default,
209    border: lightTheme.border.default,
210    notification: lightTheme.highlight.accent,
211  },
212};
213
214export const darkNavigationTheme: NavigationTheme = {
215  dark: true,
216  colors: {
217    primary: darkTheme.link.default,
218    background: darkTheme.background.screen,
219    card: darkTheme.background.screen,
220    text: darkTheme.text.default,
221    border: darkTheme.border.default,
222    notification: darkTheme.highlight.accent,
223  },
224};
225
226export const border = {
227  default: { borderColor: lightTheme.border.default, borderWidth: 1 },
228  warning: { borderColor: lightTheme.border.warning, borderWidth: 1 },
229  hairline: { borderColor: lightTheme.border.default, borderWidth: StyleSheet.hairlineWidth },
230};
231
232export const borderDark = {
233  default: { borderColor: darkTheme.border.default, borderWidth: 1 },
234  warning: { borderColor: darkTheme.border.warning, borderWidth: 1 },
235  error: { borderColor: darkTheme.border.error, borderWidth: 1 },
236  hairline: { borderColor: darkTheme.border.default, borderWidth: StyleSheet.hairlineWidth },
237};
238