1import { spacing, lightTheme, darkTheme, borderRadius } from '@expo/styleguide-native'; 2import { TextStyle, Platform } 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: Platform.OS === 'ios' ? 'Menlo' : 'monospace', 119 }, 120 InterBlack: { fontFamily: 'Inter-Black' }, 121 InterBlackItalic: { fontFamily: 'Inter-BlackItalic' }, 122 InterBold: { fontFamily: 'Inter-Bold' }, 123 InterBoldItalic: { fontFamily: 'Inter-BoldItalic' }, 124 InterExtraBold: { fontFamily: 'Inter-ExtraBold' }, 125 InterExtraBoldItalic: { fontFamily: 'Inter-ExtraBoldItalic' }, 126 InterExtraLight: { fontFamily: 'Inter-ExtraLight' }, 127 InterExtraLightItalic: { fontFamily: 'Inter-ExtraLightItalic' }, 128 InterRegular: { fontFamily: 'Inter-Regular' }, 129 InterItalic: { fontFamily: 'Inter-Italic' }, 130 InterLight: { fontFamily: 'Inter-Light' }, 131 InterLightItalic: { fontFamily: 'Inter-LightItalic' }, 132 InterMedium: { fontFamily: 'Inter-Medium' }, 133 InterMediumItalic: { fontFamily: 'Inter-MediumItalic' }, 134 InterSemiBold: { fontFamily: 'Inter-SemiBold' }, 135 InterSemiBoldItalic: { fontFamily: 'Inter-SemiBoldItalic' }, 136 InterThin: { fontFamily: 'Inter-Thin' }, 137 InterThinItalic: { fontFamily: 'Inter-ThinItalic' }, 138 }, 139 140 weight: { 141 thin: { fontWeight: '100' as TextStyle['fontWeight'] }, 142 extralight: { fontWeight: '200' as TextStyle['fontWeight'] }, 143 light: { fontWeight: '300' as TextStyle['fontWeight'] }, 144 normal: { fontWeight: '400' as TextStyle['fontWeight'] }, 145 medium: { fontWeight: '500' as TextStyle['fontWeight'] }, 146 semibold: { fontWeight: '600' as TextStyle['fontWeight'] }, 147 bold: { fontWeight: '700' as TextStyle['fontWeight'] }, 148 extrabold: { fontWeight: '800' as TextStyle['fontWeight'] }, 149 black: { fontWeight: '900' as TextStyle['fontWeight'] }, 150 }, 151 152 color: { 153 default: { color: lightTheme.text.default }, 154 error: { color: lightTheme.text.error }, 155 warning: { color: lightTheme.text.warning }, 156 success: { color: lightTheme.text.success }, 157 secondary: { color: lightTheme.text.secondary }, 158 primary: { color: lightTheme.button.primary.background }, 159 link: { color: lightTheme.link.default }, 160 }, 161}; 162 163export const textDark = { 164 base: { 165 color: darkTheme.text.default, 166 }, 167 168 color: { 169 default: { color: darkTheme.text.default }, 170 error: { color: darkTheme.text.error }, 171 warning: { color: darkTheme.text.warning }, 172 success: { color: darkTheme.text.success }, 173 secondary: { color: darkTheme.text.secondary }, 174 primary: { color: darkTheme.button.primary.background }, 175 link: { color: darkTheme.link.default }, 176 }, 177}; 178 179export const bg = { 180 none: { backgroundColor: 'transparent' }, 181 default: { backgroundColor: lightTheme.background.default }, 182 secondary: { backgroundColor: lightTheme.background.secondary }, 183 overlay: { backgroundColor: lightTheme.background.overlay }, 184 success: { backgroundColor: lightTheme.background.success }, 185 warning: { backgroundColor: lightTheme.background.warning }, 186 error: { backgroundColor: lightTheme.background.error }, 187}; 188 189export const bgDark = { 190 default: { backgroundColor: darkTheme.background.default }, 191 secondary: { backgroundColor: darkTheme.background.secondary }, 192 overlay: { backgroundColor: darkTheme.background.overlay }, 193 success: { backgroundColor: darkTheme.background.success }, 194 warning: { backgroundColor: darkTheme.background.warning }, 195 error: { backgroundColor: darkTheme.background.error }, 196}; 197 198type NavigationTheme = { 199 dark: boolean; 200 colors: { 201 primary: string; 202 background: string; 203 card: string; 204 text: string; 205 border: string; 206 notification: string; 207 }; 208}; 209 210export const lightNavigationTheme: NavigationTheme = { 211 dark: false, 212 colors: { 213 primary: lightTheme.button.primary.background, 214 background: lightTheme.background.screen, 215 card: lightTheme.background.default, 216 text: lightTheme.text.default, 217 border: lightTheme.border.default, 218 notification: lightTheme.highlight.accent, 219 }, 220}; 221 222export const darkNavigationTheme: NavigationTheme = { 223 dark: true, 224 colors: { 225 primary: darkTheme.link.default, 226 background: darkTheme.background.screen, 227 card: darkTheme.background.screen, 228 text: darkTheme.text.default, 229 border: darkTheme.border.default, 230 notification: darkTheme.highlight.accent, 231 }, 232}; 233