1import { spacing, lightTheme, darkTheme, borderRadius } from '@expo/styleguide-native';
2import { TextStyle } from 'react-native';
3
4type SpacingKey = `${keyof typeof spacing}`;
5type DescriptiveScale = 'micro' | 'tiny' | 'small' | 'medium' | 'large' | 'xl';
6type Scale = Record<SpacingKey | DescriptiveScale, number>;
7
8export const scale: Scale = {
9  micro: spacing[0.5],
10  tiny: spacing[1],
11  small: spacing[3],
12  medium: spacing[4],
13  large: spacing[6],
14  xl: spacing[8],
15  ...spacing,
16};
17
18function fullSpacingScaleForAttributes(attributes: string[]) {
19  const obj = {};
20
21  Object.keys(scale).forEach((key) => {
22    key = `${key}`;
23    const value = {};
24
25    attributes.forEach((attribute) => {
26      value[attribute] = scale[key];
27    });
28
29    obj[key] = value;
30  });
31
32  return obj as Record<SpacingKey | DescriptiveScale, any>;
33}
34
35export const padding = {
36  padding: fullSpacingScaleForAttributes(['padding']),
37  px: fullSpacingScaleForAttributes(['paddingHorizontal']),
38  py: fullSpacingScaleForAttributes(['paddingVertical']),
39  pb: fullSpacingScaleForAttributes(['paddingBottom']),
40  pt: fullSpacingScaleForAttributes(['paddingTop']),
41};
42
43export const margin = {
44  margin: fullSpacingScaleForAttributes(['margin']),
45  mx: fullSpacingScaleForAttributes(['marginHorizontal']),
46  my: fullSpacingScaleForAttributes(['marginVertical']),
47  mb: fullSpacingScaleForAttributes(['marginBottom']),
48  mt: fullSpacingScaleForAttributes(['marginTop']),
49};
50
51export const width = fullSpacingScaleForAttributes(['width']);
52export const height = fullSpacingScaleForAttributes(['height']);
53
54export const rounded = {
55  rounded: {
56    none: { borderRadius: 0 },
57    small: { borderRadius: borderRadius.small },
58    medium: { borderRadius: borderRadius.medium },
59    large: { borderRadius: borderRadius.large },
60    full: { borderRadius: 99999 },
61  },
62
63  roundedTop: {
64    none: { borderTopLeftRadius: 0, borderTopRightRadius: 0 },
65    small: { borderTopLeftRadius: borderRadius.small, borderTopRightRadius: borderRadius.small },
66    medium: {
67      borderTopLeftRadius: borderRadius.medium,
68      borderTopRightRadius: borderRadius.medium,
69    },
70    large: { borderTopLeftRadius: borderRadius.large, borderTopRightRadius: borderRadius.large },
71    full: { borderTopLeftRadius: 9999, borderTopRightRadius: 9999 },
72  },
73
74  roundedBottom: {
75    none: { borderBottomLeftRadius: 0, borderBottomRightRadius: 0 },
76    small: {
77      borderBottomLeftRadius: borderRadius.small,
78      borderBottomRightRadius: borderRadius.small,
79    },
80    medium: {
81      borderBottomLeftRadius: borderRadius.medium,
82      borderBottomRightRadius: borderRadius.medium,
83    },
84    large: {
85      borderBottomLeftRadius: borderRadius.large,
86      borderBottomRightRadius: borderRadius.large,
87    },
88    full: { borderBottomLeftRadius: 9999, borderBottomRightRadius: 9999 },
89  },
90};
91
92export const text = {
93  align: {
94    center: { textAlign: 'center' as TextStyle['textAlign'] },
95  },
96
97  size: {
98    small: {
99      fontSize: 12,
100      lineHeight: 14,
101    },
102    medium: {
103      fontSize: 16,
104      lineHeight: 18,
105    },
106    large: {
107      fontSize: 18,
108      lineHeight: 24,
109    },
110  },
111
112  leading: {
113    large: { lineHeight: 18 },
114  },
115
116  type: {
117    mono: {
118      fontFamily: 'Menlo',
119    },
120  },
121
122  weight: {
123    thin: { fontWeight: '100' as TextStyle['fontWeight'] },
124    extralight: { fontWeight: '200' as TextStyle['fontWeight'] },
125    light: { fontWeight: '300' as TextStyle['fontWeight'] },
126    normal: { fontWeight: '400' as TextStyle['fontWeight'] },
127    medium: { fontWeight: '500' as TextStyle['fontWeight'] },
128    semibold: { fontWeight: '600' as TextStyle['fontWeight'] },
129    bold: { fontWeight: '700' as TextStyle['fontWeight'] },
130    extrabold: { fontWeight: '800' as TextStyle['fontWeight'] },
131    black: { fontWeight: '900' as TextStyle['fontWeight'] },
132  },
133
134  color: {
135    default: { color: lightTheme.text.default },
136    error: { color: lightTheme.text.error },
137    warning: { color: lightTheme.text.warning },
138    success: { color: lightTheme.text.success },
139    secondary: { color: lightTheme.text.secondary },
140    primary: { color: lightTheme.button.primary.background },
141  },
142};
143
144export const textDark = {
145  base: {
146    color: darkTheme.text.default,
147  },
148
149  color: {
150    default: { color: darkTheme.text.default },
151    error: { color: darkTheme.text.error },
152    warning: { color: darkTheme.text.warning },
153    success: { color: darkTheme.text.success },
154    secondary: { color: darkTheme.text.secondary },
155    primary: { color: darkTheme.button.primary.background },
156  },
157};
158
159export const bg = {
160  none: { backgroundColor: 'transparent' },
161  default: { backgroundColor: lightTheme.background.default },
162  secondary: { backgroundColor: lightTheme.background.secondary },
163  success: { backgroundColor: lightTheme.background.success },
164  warning: { backgroundColor: lightTheme.background.warning },
165  error: { backgroundColor: lightTheme.background.error },
166};
167
168export const bgDark = {
169  default: { backgroundColor: darkTheme.background.default },
170  secondary: { backgroundColor: darkTheme.background.secondary },
171  success: { backgroundColor: darkTheme.background.success },
172  warning: { backgroundColor: darkTheme.background.warning },
173  error: { backgroundColor: darkTheme.background.error },
174};
175
176type NavigationTheme = {
177  dark: boolean;
178  colors: {
179    primary: string;
180    background: string;
181    card: string;
182    text: string;
183    border: string;
184    notification: string;
185  };
186};
187
188export const lightNavigationTheme: NavigationTheme = {
189  dark: false,
190  colors: {
191    primary: lightTheme.button.primary.background,
192    background: lightTheme.background.secondary,
193    card: lightTheme.background.default,
194    text: lightTheme.text.default,
195    border: lightTheme.border.default,
196    notification: lightTheme.highlight.accent,
197  },
198};
199
200export const darkNavigationTheme: NavigationTheme = {
201  dark: true,
202  colors: {
203    primary: darkTheme.button.primary.background,
204    background: darkTheme.background.secondary,
205    card: darkTheme.background.default,
206    text: darkTheme.text.default,
207    border: darkTheme.border.default,
208    notification: darkTheme.highlight.accent,
209  },
210};
211