UNPKG

@hoddy-ui/next

Version:

Core rich react native components written in typescript, with support for expo-router

1 lines 118 kB
{"version":3,"sources":["../../src/theme/colors.ts","../../src/config/KeyManager.ts","../../src/config/index.ts","../components/AdaptiveStatusBarNext.tsx","../../src/hooks.ts","../../src/theme/index.tsx","../../src/Components/FlashMessage.tsx","../../src/Components/Typography.tsx","../../src/Components/AlertX.tsx","../../src/Components/Avatar.tsx","../../src/Components/Button.tsx","../../src/Components/Checkbox.tsx","../../src/Components/FormWrapper.tsx","../../src/Components/StarRating.tsx","../../src/Components/Popup.tsx","../../src/Components/Grid.tsx","../../src/Components/Locator.tsx","../../src/Components/List.tsx","../../src/Components/TextField.tsx","../../src/Components/SelectMenu.tsx","../../src/Components/SafeAreaView.tsx","../../src/Components/Divider.tsx","../../src/Components/Spinner.tsx","../../src/Components/OTPInput.tsx","../index.ts"],"sourcesContent":["import { ThemeTypes, extraColorTypes } from \"../types\";\n\nlet extraColors: extraColorTypes = {};\n\nexport const setExtraColors = (c: extraColorTypes) => (extraColors = c);\n\nexport default function colors(theme: ThemeTypes) {\n const lightColors = {\n white: {\n 1: \"#ffffff\",\n 2: \"#f7f7f7\",\n 3: \"#eeeeee\",\n 4: \"#dddddd\",\n 5: \"#bbbbbb\",\n ...extraColors?.light?.white,\n },\n black: {\n 1: \"#888888\",\n 2: \"#777777\",\n 3: \"#555555\",\n 4: \"#333333\",\n 5: \"#000000\",\n ...extraColors?.light?.black,\n },\n };\n\n const darkColors = {\n black: {\n 1: \"#ffffff\",\n 2: \"#f7f7f7\",\n 3: \"#eeeeee\",\n 4: \"#dddddd\",\n 5: \"#aaaaaa\",\n ...extraColors?.dark?.black,\n },\n white: {\n 1: \"#060606\",\n 2: \"#222222\",\n 3: \"#333333\",\n 4: \"#444444\",\n 5: \"#555555\",\n ...extraColors?.dark?.white,\n },\n dark: {\n main: \"#f2f3f4\",\n light: \"#ffffff\",\n dark: \"#dddddd\",\n text: \"#000000\",\n ...extraColors?.dark?.dark,\n },\n light: {\n main: \"#111111\",\n light: \"#555555\",\n dark: \"#333333\",\n text: \"#ffffff\",\n ...extraColors?.dark?.light,\n },\n textSecondary: {\n main: \"#666666\",\n light: \"#777777\",\n dark: \"#444444\",\n text: \"#ffffff\",\n ...extraColors?.dark?.textSecondary,\n },\n primary: {\n main: \"#ff8800\",\n light: \"#feffd3\",\n dark: \"#ffaa00\",\n text: \"#ffffff\",\n ...extraColors?.light?.primary,\n ...extraColors?.dark?.primary,\n },\n };\n\n const dynamicColors = theme === \"dark\" ? darkColors : lightColors;\n return {\n ...extraColors[theme],\n primary: {\n main: \"#ff8800\",\n light: \"#feffd3\",\n dark: \"#ffaa00\",\n text: \"#ffffff\",\n ...extraColors?.light?.primary,\n },\n secondary: {\n main: \"#ff1111\",\n light: \"#ff4433\",\n dark: \"#dd0000\",\n text: \"#ffffff\",\n ...extraColors?.light?.secondary,\n },\n light: {\n main: \"#ffffff\",\n light: \"#ffffff\",\n dark: \"#dddddd\",\n text: \"#000000\",\n ...extraColors?.light?.light,\n },\n dark: {\n main: \"#000000\",\n light: \"#777777\",\n dark: \"#111111\",\n text: \"#ffffff\",\n ...extraColors?.light?.dark,\n },\n textSecondary: {\n main: \"#aaaaaa\",\n light: \"#bbbbbb\",\n dark: \"#777777\",\n text: \"#112233\",\n ...extraColors?.light?.textSecondary,\n },\n blue: {\n main: \"#0099ff\",\n light: \"#3399ff\",\n dark: \"#002288\",\n text: \"#ffffff\",\n ...extraColors?.light?.blue,\n },\n info: {\n main: \"#0099ff\",\n light: \"#33aaff\",\n dark: \"#0088aa\",\n text: \"#ffffff\",\n ...extraColors?.light?.info,\n },\n success: {\n main: \"#00aa44\",\n text: \"#ffffff\",\n light: \"#55cc33\",\n dark: \"#006622\",\n ...extraColors?.light?.success,\n },\n warning: {\n main: \"#ffaa22\",\n light: \"#ffcc77\",\n dark: \"#ff9900\",\n text: \"#ffffff\",\n ...extraColors?.light?.warning,\n },\n error: {\n main: \"#dd2222\",\n text: \"#ffffff\",\n light: \"#ff4433\",\n dark: \"#aa2200\",\n ...extraColors?.light?.error,\n },\n ...dynamicColors,\n };\n}\n","type configTypes = {\n GOOGLE_MAP_API_KEY?: string;\n DEFAULT_FONT_FAMILY?: string;\n EDGE_TO_EDGE?: boolean;\n};\n\nlet config: configTypes = {\n GOOGLE_MAP_API_KEY: \"\",\n EDGE_TO_EDGE: false,\n};\n\nexport function setConfig(key: configTypes): void {\n config = key;\n}\n\nexport function getConfig(): configTypes {\n return config;\n}\n","// import * as fs from \"fs\";\nimport { setExtraColors } from \"../theme/colors\";\nimport { extraColorTypes } from \"../types\";\nimport { setConfig } from \"./KeyManager\";\n\ntype configProps = {\n googleMapApiKey?: string;\n colors?: extraColorTypes;\n fontFamily?: string;\n edgeToEdge?: boolean;\n};\n\nexport function initialize(config: configProps): void {\n try {\n setConfig({\n GOOGLE_MAP_API_KEY: config.googleMapApiKey,\n DEFAULT_FONT_FAMILY: config.fontFamily,\n EDGE_TO_EDGE: config.edgeToEdge ?? false,\n });\n if (config.colors) setExtraColors(config.colors);\n } catch (error) {\n console.error(\"Error reading the config file:\", error);\n }\n}\n","import { useFocusEffect } from \"expo-router\";\nimport React, { useState } from \"react\";\nimport { Platform, StatusBar } from \"react-native\";\nimport { useColors, useTheme } from \"../../src/hooks\";\n\nconst AdaptiveStatusBar = ({ translucent = false }) => {\n const [focused, setFocused] = useState(false);\n const colors = useColors();\n const theme = useTheme();\n const statusbarHandler = () => {\n StatusBar.setBarStyle(theme === \"dark\" ? \"light-content\" : \"dark-content\");\n if (Platform.OS === \"android\") {\n StatusBar.setBackgroundColor(\n translucent ? \"transparent\" : colors.white[1]\n );\n StatusBar.setTranslucent(true);\n }\n };\n\n useFocusEffect(\n React.useCallback(() => {\n statusbarHandler();\n }, [theme])\n );\n\n React.useEffect(() => {\n statusbarHandler();\n }, [theme]);\n return <></>;\n};\n\nexport default AdaptiveStatusBar;\n","import { useContext } from \"react\";\nimport { Dimensions, Platform } from \"react-native\";\nimport { vs } from \"react-native-size-matters\";\nimport { UIThemeContext } from \"./theme\";\nimport colors from \"./theme/colors\";\n\nexport const useColors = () => {\n const { themeState } = useContext(UIThemeContext);\n return colors(themeState.value);\n};\n\nexport const useTheme = () => {\n const { themeState } = useContext(UIThemeContext);\n return themeState.value;\n};\nexport const useNavScreenOptions = (type: \"stack\" | \"tab\" | \"drawer\") => {\n const colors = useColors();\n const theme = useTheme();\n const options: any = {\n stack: {\n headerShown: false,\n\n headerStyle: {\n backgroundColor: colors.white[1],\n },\n headerShadowVisible: false,\n contentStyle: {\n backgroundColor: colors.white[1],\n },\n headerTitleStyle: {\n color: colors.black[1],\n },\n headerTintColor:\n Platform.OS === \"android\" ? colors.black[1] : colors.blue.light,\n },\n tab: {\n headerShown: false,\n headerTintColor: colors.dark.main,\n tabBarStyle: {\n borderTopColor: theme === \"dark\" ? colors.light.main : colors.white[2],\n borderTopWidth: 1,\n // shadowColor: \"#000\",\n // shadowOffset: { height: -3, width: 0 },\n // shadowRadius: 7,\n // shadowOpacity: 0.1,\n backgroundColor: colors.white[1],\n },\n tabBarActiveTintColor: colors.blue.main,\n tabBarInactiveTintColor: colors.textSecondary.main,\n tabBarLabelStyle: {\n // fontSize: ms(12),\n },\n },\n drawer: {\n headerShown: false,\n drawerActiveTintColor: colors.primary.main,\n drawerInactiveTintColor: colors.textSecondary.main,\n sceneContainerStyle: {\n backgroundColor: colors.white[2],\n },\n drawerStyle: {\n backgroundColor: colors.white[1],\n },\n headerStyle: {\n backgroundColor: colors.white[1],\n },\n headerTitleStyle: {\n color: colors.dark.main,\n },\n },\n };\n\n if (Platform.OS === \"android\") {\n options.tab.tabBarStyle.height = Dimensions.get(\"screen\").height * 0.08;\n options.tab.tabBarStyle.paddingBottom = vs(15);\n }\n return options[type];\n};\n","import AsyncStorage from \"@react-native-async-storage/async-storage\";\nimport * as NavigationBar from \"expo-navigation-bar\";\nimport * as SystemUI from \"expo-system-ui\";\nimport React, { createContext, useEffect, useReducer } from \"react\";\nimport { Platform, useColorScheme } from \"react-native\";\nimport { SafeAreaProvider } from \"react-native-safe-area-context\";\nimport FlashMessage from \"../Components/FlashMessage\";\nimport { getConfig } from \"../config/KeyManager\";\nimport { useColors, useTheme } from \"../hooks\";\nimport {\n ThemeActionTypes,\n ThemeContext,\n ThemeProviderProps,\n ThemeState,\n ThemeTypes,\n} from \"../types\";\n\nexport const UIThemeContext = createContext<ThemeContext>({\n themeState: { mode: \"default\", value: \"light\" },\n});\n\nfunction themeReducer(\n state: ThemeState,\n { type, payload }: ThemeActionTypes\n): ThemeState {\n // Platform\n\n switch (type) {\n case \"dark\":\n return { mode: \"dark\", value: \"dark\" };\n case \"default\":\n return { mode: \"default\", value: payload! };\n case \"light\":\n return { mode: \"light\", value: \"light\" };\n default:\n return state;\n }\n}\n\nconst ConfigureSystemUI = () => {\n const theme = useTheme();\n const colors = useColors();\n\n useEffect(() => {\n const config = getConfig();\n if (colors) {\n SystemUI.setBackgroundColorAsync(colors.white[1]);\n if (Platform.OS === \"android\" && !config.EDGE_TO_EDGE) {\n NavigationBar.setBackgroundColorAsync(colors.white[1]);\n if (theme === \"dark\") {\n NavigationBar.setButtonStyleAsync(\"light\");\n } else {\n NavigationBar.setButtonStyleAsync(\"dark\");\n }\n }\n }\n }, [colors, theme]);\n\n return <></>;\n};\n\nexport const UIThemeProvider = ({ children }: ThemeProviderProps) => {\n const [themeState, themeDispatch] = useReducer(themeReducer, {\n mode: \"default\",\n value: \"light\",\n });\n\n const colorScheme: ThemeTypes = useColorScheme()!;\n\n React.useEffect(() => {\n AsyncStorage.getItem(\"theme\").then((val: any) => {\n if (val) {\n if (val === \"default\") {\n themeDispatch({\n type: \"default\",\n payload: colorScheme,\n });\n } else\n themeDispatch({\n type: val,\n });\n } else {\n themeDispatch({\n type: \"default\",\n payload: colorScheme,\n });\n }\n });\n }, [colorScheme]);\n return (\n <SafeAreaProvider>\n <UIThemeContext.Provider\n value={{\n themeState,\n themeDispatch,\n }}\n >\n {children}\n <FlashMessage />\n <ConfigureSystemUI />\n </UIThemeContext.Provider>\n </SafeAreaProvider>\n );\n};\n","import React, { useEffect, useState } from \"react\";\nimport {\n LayoutAnimation,\n Touchable,\n TouchableOpacity,\n View,\n} from \"react-native\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\nimport { ScaledSheet } from \"react-native-size-matters\";\nimport { useColors } from \"../hooks\";\nimport { MaterialIcons } from \"@expo/vector-icons\";\nimport { FlashMessageProps } from \"../types\";\nimport Typography from \"./Typography\";\n\nexport let showFlashMessage: (msg: FlashMessageProps) => void = () => {};\n\nconst FlashMessage: React.FC = () => {\n const { top } = useSafeAreaInsets();\n const [message, setMessage] = useState<null | FlashMessageProps>(null);\n const [show, setShow] = useState(false);\n const colors = useColors();\n const type = message?.type || \"success\";\n\n showFlashMessage = (msg: FlashMessageProps) => {\n setMessage(msg);\n setTimeout(() => {\n setShow(true);\n }, 50);\n\n setTimeout(() => {\n setShow(false);\n setTimeout(() => {\n setMessage(null);\n }, 500);\n }, msg.duration || 3000);\n };\n useEffect(() => {\n LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);\n }, [show]);\n\n const styles = ScaledSheet.create({\n root: {\n position: \"absolute\",\n top: show ? 0 : -200,\n zIndex: 1000,\n left: 0,\n paddingTop: top + 10,\n paddingHorizontal: \"15@ms\",\n backgroundColor: colors[type].main,\n width: \"100%\",\n borderBottomLeftRadius: 10,\n borderBottomRightRadius: 10,\n paddingBottom: \"15@ms\",\n },\n\n action: {\n borderRadius: 20,\n marginTop: \"10@vs\",\n flexDirection: \"row\",\n justifyContent: \"center\",\n paddingHorizontal: \"20@ms\",\n paddingVertical: \"8@vs\",\n backgroundColor: \"#fff3\",\n },\n });\n\n return (\n <View style={styles.root}>\n <View style={{ flexDirection: \"row\" }}>\n <View style={{ flex: 1, marginRight: 10 }}>\n {message?.title && (\n <Typography\n variant=\"h6\"\n fontWeight={600}\n gutterBottom={3}\n style={{ color: \"#fff\" }}\n >\n {message?.title}\n </Typography>\n )}\n <Typography style={{ color: \"#fff\" }}>{message?.message}</Typography>\n </View>\n {/* <MaterialIcons color=\"#fff\" size={36} name=\"error-outline\" /> */}\n </View>\n\n {message?.actions?.map((cur, i) => (\n <TouchableOpacity key={i} style={styles.action} onPress={cur.onPress}>\n <Typography fontWeight={700} style={{ color: \"#fff\" }}>\n {cur.title}\n </Typography>\n </TouchableOpacity>\n ))}\n </View>\n );\n};\n\nexport default FlashMessage;\n","import React, { forwardRef } from \"react\";\nimport { StyleSheet, Text } from \"react-native\";\nimport { moderateScale, verticalScale } from \"react-native-size-matters\";\nimport { useColors } from \"../hooks\";\nimport { TypographyProps } from \"../types\";\nimport { getConfig } from \"../config/KeyManager\";\n\nconst Typography: React.FC<TypographyProps> = forwardRef(\n (\n {\n children,\n color = \"dark\",\n style = {},\n textCase = null,\n variant = \"body1\",\n align = \"left\",\n gutterBottom = 0,\n adjustsFontSizeToFit,\n fontWeight = 400,\n fontFamily, // NEW PROP ADDED\n ...props\n },\n ref\n ) => {\n const colors: any = useColors();\n const fontSize = {\n h1: moderateScale(42),\n h2: moderateScale(37),\n h3: moderateScale(32),\n h4: moderateScale(27),\n h5: moderateScale(22),\n h6: moderateScale(17),\n body1: moderateScale(15),\n body2: moderateScale(12),\n caption: moderateScale(10),\n };\n\n const styles: any = StyleSheet.create({\n text: {\n fontSize: fontSize[variant],\n marginBottom: verticalScale(gutterBottom) || 0,\n color: colors[color]?.main || color,\n textTransform: textCase,\n alignItems: \"center\",\n textAlign: align,\n fontWeight: fontWeight,\n fontFamily: fontFamily || getConfig().DEFAULT_FONT_FAMILY || undefined, // Use custom font if provided, else default\n },\n });\n\n return (\n <Text\n ref={ref as any}\n adjustsFontSizeToFit={adjustsFontSizeToFit}\n style={[styles.text, style]} // Ensures external styles are applied\n {...props}\n >\n {children}\n </Text>\n );\n }\n);\n\nexport default Typography;\n","import { MaterialIcons } from \"@expo/vector-icons\";\nimport React from \"react\";\nimport { View } from \"react-native\";\nimport { ScaledSheet } from \"react-native-size-matters\";\nimport { useColors } from \"../hooks\";\nimport { AlertXProps } from \"../types\";\nimport Typography from \"./Typography\";\n\nconst AlertX: React.FC<AlertXProps> = ({\n type = \"info\",\n variant = \"contained\",\n title,\n gutterBottom = 0,\n body,\n style = {},\n}) => {\n const colors = useColors();\n\n const styles: any = ScaledSheet.create({\n container: {\n padding: 20,\n paddingTop: 10,\n paddingBottom: 10,\n borderRadius: 8,\n alignItems: \"center\",\n flexDirection: \"row\",\n marginBottom: gutterBottom + \"@ms\",\n backgroundColor: colors[type].main + (variant === \"contained\" ? \"\" : \"3\"),\n },\n title: {\n color: variant === \"contained\" ? \"#fff\" : colors[type].main,\n },\n body: {\n color: variant === \"contained\" ? \"#fff\" : colors[type].main,\n },\n });\n return (\n <View style={{ ...styles.container, ...style }}>\n <View style={{ width: \"80%\" }}>\n <Typography style={styles.title} gutterBottom={3} fontWeight={700}>\n {title}\n </Typography>\n {body && (\n <Typography fontWeight={700} variant=\"body2\" style={styles.body}>\n {body}\n </Typography>\n )}\n </View>\n <View style={{ marginLeft: \"auto\" }}>\n <MaterialIcons\n color={variant === \"contained\" ? \"#fff\" : colors[type].main}\n size={36}\n name={type === \"success\" ? \"check\" : type}\n />\n </View>\n </View>\n );\n};\n\nexport default AlertX;\n","import { AntDesign } from \"@expo/vector-icons\";\nimport React from \"react\";\nimport { Image, View } from \"react-native\";\nimport { ScaledSheet } from \"react-native-size-matters\";\nimport { useColors } from \"../hooks\";\nimport { AvatarProps } from \"../types\";\nimport Typography from \"./Typography\";\n\nconst Avatar: React.FC<AvatarProps> = ({\n color = \"dark\",\n label,\n variant = \"contained\",\n source,\n size = 48,\n style = {},\n}) => {\n const colors = useColors();\n const styles: any = ScaledSheet.create({\n root: {\n borderRadius: 150,\n height: size + \"@ms\",\n width: size + \"@ms\",\n alignItems: \"center\",\n justifyContent: \"center\",\n overflow: \"hidden\",\n borderWidth: variant === \"outlined\" ? 5 : 0,\n borderColor: variant === \"outlined\" ? \"#fff\" : \"#0000\",\n backgroundColor:\n variant === \"outlined\"\n ? null\n : label\n ? colors[color].main\n : colors.white[4],\n ...style,\n },\n image: {\n height: \"110%\",\n width: \"110%\",\n },\n });\n\n return (\n <View style={styles.root}>\n {source ? (\n <Image resizeMode=\"cover\" style={styles.image} source={source} />\n ) : label ? (\n <Typography style={{ color: colors[color].text }}>\n {label[0]}\n </Typography>\n ) : (\n <AntDesign name=\"user\" color=\"#fff\" size={Math.round(size / 1.5)} />\n )}\n </View>\n );\n};\n\nexport default Avatar;\n","import { Ionicons, MaterialIcons } from \"@expo/vector-icons\";\nimport React, { forwardRef } from \"react\";\nimport { ActivityIndicator, Text, TouchableOpacity } from \"react-native\";\nimport { ScaledSheet, moderateScale } from \"react-native-size-matters\";\nimport { getConfig } from \"../config/KeyManager\";\nimport { useColors, useTheme } from \"../hooks\";\nimport { ButtonProps, IconButtonProps, LinkButtonProps } from \"../types\";\n\nexport const LinkButton: React.FC<LinkButtonProps> = ({\n title,\n style = {},\n color = \"blue\",\n fontSize = 12,\n fontWeight = \"400\",\n disabled,\n onPress = () => {},\n}) => {\n const colors = useColors();\n\n const styles: any = ScaledSheet.create({\n text: {\n fontSize: moderateScale(fontSize),\n fontWeight: fontWeight,\n fontFamily: getConfig().DEFAULT_FONT_FAMILY || \"System\",\n color: disabled ? \"#777\" : colors[color].main,\n },\n });\n return (\n <TouchableOpacity onPress={onPress} disabled={disabled}>\n <Text style={{ ...styles.text, ...style }}>{title}</Text>\n </TouchableOpacity>\n );\n};\n\nexport const IconButton: React.FC<IconButtonProps> = ({\n style = {},\n color = \"dark\",\n disabled,\n icon,\n elevation,\n bg = false,\n size = 24,\n containerStyles = {},\n onPress = () => {},\n iconType = \"material\",\n}) => {\n const colors = useColors();\n const theme = useTheme();\n const bgColor = theme === \"light\" ? \"#fff\" : \"#222\";\n const styles: any = ScaledSheet.create({\n container: {\n alignSelf: \"flex-start\",\n flexGrow: 0,\n backgroundColor: bg ? bgColor : elevation! > 0 ? bgColor : null,\n padding: \"5@ms\",\n shadowColor: \"#000\",\n shadowOpacity: 0.1,\n shadowOffset: {\n height: 1,\n width: 0,\n },\n height: bg ? size + 20 + \"@ms\" : undefined,\n width: bg ? size + 20 + \"@ms\" : undefined,\n alignItems: \"center\",\n justifyContent: \"center\",\n shadowRadius: elevation,\n elevation: elevation,\n borderRadius: size * 5,\n },\n text: {\n color: disabled ? \"#777\" : colors[color].main,\n },\n });\n\n const IconComp = {\n material: MaterialIcons,\n ion: Ionicons,\n }[iconType];\n return (\n <TouchableOpacity\n onPress={onPress}\n activeOpacity={0.3}\n style={{ ...styles.container, ...containerStyles }}\n >\n <IconComp style={{ ...styles.text, ...style }} name={icon} size={size} />\n </TouchableOpacity>\n );\n};\n\nconst Button: React.FC<ButtonProps> = forwardRef(\n (\n {\n elevation = 0,\n onPress = () => {},\n disabled = false,\n title,\n loading,\n size = \"normal\",\n rounded = false,\n gutterBottom,\n style = {},\n fullWidth = false,\n translucent = false,\n color = \"primary\",\n variant = \"contained\",\n start,\n end,\n },\n ref\n ) => {\n const colors = useColors();\n\n const styles: any = ScaledSheet.create({\n con: {\n flexDirection: \"row\",\n alignItems: \"center\",\n alignSelf: \"flex-start\",\n justifyContent: \"center\",\n backgroundColor:\n variant === \"text\" || variant === \"outlined\"\n ? null\n : translucent\n ? translucent === \"dark\"\n ? colors.white[3] + \"22\"\n : colors.black[3] + \"22\"\n : loading\n ? colors[color].light\n : disabled\n ? colors.white[4]\n : colors[color].main,\n borderRadius: rounded ? 30 : 10,\n elevation: variant === \"text\" ? 0 : elevation,\n paddingVertical:\n size === \"small\" ? 8 : size === \"large\" ? \"15@ms\" : \"13@ms\",\n paddingHorizontal: size === \"small\" ? \"10@ms\" : \"18@ms\",\n borderColor: colors[color].main,\n borderWidth: variant === \"outlined\" ? 1 : 0,\n shadowColor: \"#000\",\n shadowRadius: elevation,\n marginBottom: gutterBottom,\n shadowOffset: {\n height: elevation / 2,\n width: 0,\n },\n shadowOpacity: variant === \"text\" ? 0 : 0.3,\n width: fullWidth ? \"100%\" : null,\n ...style,\n },\n text: {\n color: disabled\n ? variant === \"text\" || variant === \"outlined\"\n ? colors.black[1]\n : colors[color].text\n : colors[color][\n variant === \"text\" || variant === \"outlined\" ? \"main\" : \"text\"\n ],\n fontWeight: variant === \"outlined\" ? \"700\" : \"500\",\n fontSize: size === \"small\" ? \"12@ms\" : \"16@ms\",\n fontFamily: getConfig().DEFAULT_FONT_FAMILY || \"System\",\n },\n });\n\n return (\n <TouchableOpacity\n ref={ref as any}\n onPress={onPress}\n disabled={disabled}\n style={styles.con}\n >\n {start}\n {loading && (\n <ActivityIndicator\n size=\"small\"\n color={colors[color].text}\n style={{ marginRight: 10 }}\n />\n )}\n <Text style={styles.text}>{title}</Text>\n {end}\n </TouchableOpacity>\n );\n }\n);\n\nexport default Button;\n","import { MaterialCommunityIcons } from \"@expo/vector-icons\";\nimport React, { FC } from \"react\";\nimport { TouchableOpacity, View } from \"react-native\";\nimport { ScaledSheet } from \"react-native-size-matters\";\nimport { useColors } from \"../hooks\";\nimport { CheckboxProps } from \"../types\";\n\nexport const CheckBox: FC<CheckboxProps> = ({\n color = \"primary\",\n checked,\n size = 24,\n label,\n style = {},\n onChange,\n}) => {\n const iconName = checked ? \"checkbox-marked\" : \"checkbox-blank-outline\";\n const colors = useColors();\n\n const styles = ScaledSheet.create({\n container: {\n alignItems: \"center\",\n flexDirection: \"row\",\n ...style,\n },\n });\n\n return (\n <View style={styles.container}>\n <TouchableOpacity onPress={onChange}>\n <MaterialCommunityIcons\n name={iconName}\n size={size}\n color={colors[color].main}\n />\n </TouchableOpacity>\n {label}\n </View>\n );\n};\n","import React from \"react\";\nimport {\n Keyboard,\n KeyboardAvoidingView,\n Platform,\n ScrollView,\n TouchableWithoutFeedback,\n} from \"react-native\";\nimport { ScaledSheet } from \"react-native-size-matters\";\nimport { FormWrapperProps } from \"../types\";\nexport const FormWrapper: React.FC<FormWrapperProps> = ({\n children,\n behavior = Platform.OS === \"ios\" ? \"padding\" : \"height\",\n contentContainerStyle,\n mode = \"scroll\",\n keyboardVerticalOffset = 10,\n style = {},\n onScroll,\n}) => {\n const styles = ScaledSheet.create({\n root: {\n width: \"100%\",\n flex: 1,\n ...style,\n },\n });\n return mode === \"static\" ? (\n <TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>\n <KeyboardAvoidingView\n style={styles.root}\n behavior={behavior}\n contentContainerStyle={styles.root}\n keyboardVerticalOffset={keyboardVerticalOffset}\n >\n {children}\n </KeyboardAvoidingView>\n </TouchableWithoutFeedback>\n ) : (\n <KeyboardAvoidingView\n behavior={behavior}\n style={styles.root}\n keyboardVerticalOffset={keyboardVerticalOffset}\n >\n <ScrollView\n onScroll={onScroll}\n showsVerticalScrollIndicator={false}\n scrollEventThrottle={40}\n keyboardDismissMode=\"interactive\"\n contentContainerStyle={contentContainerStyle}\n keyboardShouldPersistTaps=\"handled\"\n >\n {children}\n </ScrollView>\n </KeyboardAvoidingView>\n );\n};\n","import { Ionicons } from \"@expo/vector-icons\";\nimport * as Haptics from \"expo-haptics\";\nimport { FC, useEffect, useState } from \"react\";\nimport {\n ActivityIndicator,\n TextInput,\n TouchableOpacity,\n View,\n} from \"react-native\";\nimport { ScaledSheet } from \"react-native-size-matters\";\nimport { useColors } from \"../hooks\";\nimport { RatingInputProps, RatingStarsProps } from \"../types\";\nimport Button from \"./Button\";\nimport { Popup } from \"./Popup\";\nimport Typography from \"./Typography\";\n\nexport const RatingStars: FC<RatingStarsProps> = ({\n rating = 0,\n size = 16,\n}) => {\n const colors = useColors();\n\n const styles = ScaledSheet.create({\n root: {\n flexDirection: \"row\",\n alignItems: \"center\",\n },\n });\n return (\n <View style={styles.root}>\n {[...Array(Math.floor(rating))].map((_, index) => (\n <Ionicons key={index} name=\"star\" size={size} color=\"#FFD700\" />\n ))}\n {[...Array(5 - Math.floor(rating))].map((_, index) => (\n <Ionicons\n key={index}\n name=\"star\"\n size={size}\n color={colors.textSecondary.light}\n />\n ))}\n </View>\n );\n};\n\nexport const RatingInput: FC<RatingInputProps> = ({\n onSubmit: _onSubmit,\n rating = 0,\n size = 16,\n}) => {\n const [showReviewsModal, setShowReviewsModal] = useState(false);\n const [rate, setRate] = useState(0);\n const colors = useColors();\n const [loading, setLoading] = useState(false);\n const [review, setReview] = useState(\"\");\n const styles = ScaledSheet.create({\n root: {\n flexDirection: \"row\",\n alignItems: \"center\",\n },\n inputCon: {\n marginBottom: \"20@vs\",\n backgroundColor: colors.white[3],\n padding: \"15@ms\",\n borderRadius: 20,\n },\n input: {\n fontSize: \"16@ms\",\n color: colors.dark.main,\n height: \"100@vs\",\n },\n });\n\n useEffect(() => {\n setRate(rating);\n }, [rating]);\n const onRate = (index: number) => {\n setRate(index + 1);\n Haptics.selectionAsync();\n\n setTimeout(() => {\n setShowReviewsModal(true);\n }, 500);\n };\n\n const onSubmit = async () => {\n setLoading(true);\n setShowReviewsModal(false);\n _onSubmit && (await _onSubmit({ rating: rate, review }));\n setLoading(false);\n };\n return (\n <>\n <View style={styles.root}>\n {loading ? (\n <ActivityIndicator />\n ) : (\n [...Array(5)].map((_, index) => (\n <TouchableOpacity\n key={index}\n activeOpacity={0.9}\n onPress={() => {\n onRate(index);\n }}\n >\n <Ionicons\n style={{ marginLeft: 10 }}\n name={index < rate ? \"star\" : \"star-outline\"}\n size={size}\n color={colors.primary.light}\n />\n </TouchableOpacity>\n ))\n )}\n </View>\n <Popup\n sheet\n open={showReviewsModal}\n onClose={() => {\n setShowReviewsModal(false);\n }}\n >\n <View\n style={{\n alignItems: \"center\",\n marginBottom: 5,\n }}\n >\n <RatingStars rating={rate} size={24} />\n </View>\n <Typography\n align=\"center\"\n fontWeight={700}\n variant=\"h5\"\n gutterBottom={20}\n >\n Add to your review\n </Typography>\n\n <View style={styles.inputCon}>\n <TextInput\n style={styles.input}\n multiline\n value={review}\n onChangeText={(text) => setReview(text)}\n placeholder=\"Type review here..\"\n />\n </View>\n <Button\n gutterBottom={40}\n title=\"Submit Review\"\n loading={loading}\n disabled={loading}\n onPress={() => {\n onSubmit();\n }}\n />\n </Popup>\n </>\n );\n};\n","import {\n Keyboard,\n KeyboardAvoidingView,\n Modal,\n Platform,\n Pressable,\n StyleSheet,\n TouchableWithoutFeedback,\n View,\n} from \"react-native\";\n\nimport React, { useState } from \"react\";\nimport { ScaledSheet } from \"react-native-size-matters\";\nimport { useColors, useTheme } from \"../hooks\";\nimport { PopupProps } from \"../types\";\nimport { IconButton } from \"./Button\";\nimport Typography from \"./Typography\";\nimport { UIThemeProvider } from \"../theme\";\n\nexport const Popup: React.FC<PopupProps> = ({\n title,\n sheet,\n bare = false,\n keyboardVerticalOffset,\n children,\n open,\n onClose = () => {},\n style,\n}) => {\n const theme = useTheme();\n const colors = useColors();\n const [show, setShow] = useState(open);\n const [showSecondary, setShowSecondary] = useState(false);\n\n const styles: any = ScaledSheet.create({\n root: {\n height: \"100%\",\n width: \"100%\",\n justifyContent: sheet ? \"flex-end\" : \"center\",\n },\n avoidingView: {\n minHeight: typeof sheet === \"number\" ? sheet : undefined,\n maxHeight: \"80%\",\n zIndex: 1000,\n alignSelf: \"center\",\n maxWidth: sheet ? undefined : \"90%\",\n\n width: sheet ? \"100%\" : undefined,\n },\n container: {\n paddingBottom: sheet ? \"30@ms\" : 0,\n backgroundColor: theme === \"dark\" ? \"#111\" : colors.white[2],\n borderTopLeftRadius: 20,\n borderTopRightRadius: 20,\n borderBottomRightRadius: sheet ? 0 : 20,\n borderBottomLeftRadius: sheet ? 0 : 20,\n width: \"100%\",\n ...style,\n },\n content: {\n paddingHorizontal: bare ? undefined : \"15@ms\",\n // flex: 1,\n },\n title: {\n flexDirection: \"row\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"50@ms\",\n },\n titleIcon: {\n position: \"absolute\",\n left: \"15@ms\",\n },\n backdrop: {\n position: \"absolute\",\n height: \"100%\",\n zIndex: -1,\n width: \"100%\",\n backgroundColor: \"#000b\",\n },\n });\n\n React.useEffect(() => {\n if (open) {\n setShow(open);\n setTimeout(() => {\n setShowSecondary(open);\n }, 500);\n } else {\n closeAction();\n }\n }, [open]);\n\n const closeAction = () => {\n setShowSecondary(false);\n setTimeout(() => {\n setShow(false);\n onClose();\n }, 300);\n };\n\n return (\n <>\n <Modal\n transparent\n animationType=\"fade\"\n statusBarTranslucent\n visible={show}\n onRequestClose={closeAction}\n >\n <View style={styles.backdrop} />\n <UIThemeProvider>\n <Modal\n transparent\n animationType=\"slide\"\n statusBarTranslucent\n visible={showSecondary}\n onRequestClose={closeAction}\n >\n <TouchableWithoutFeedback onPress={Keyboard.dismiss}>\n <View style={styles.root}>\n {open && (\n <Pressable\n style={StyleSheet.absoluteFill}\n onPress={closeAction}\n />\n )}\n\n <KeyboardAvoidingView\n style={styles.avoidingView}\n keyboardVerticalOffset={keyboardVerticalOffset}\n behavior={Platform.OS === \"ios\" ? \"position\" : \"padding\"}\n >\n <View style={styles.container}>\n {!bare && (\n <View style={styles.title}>\n <View style={styles.titleIcon}>\n <IconButton\n size={20}\n icon=\"close\"\n onPress={closeAction}\n />\n </View>\n <Typography align=\"center\" fontWeight={500}>\n {title}\n </Typography>\n </View>\n )}\n\n <View style={styles.content}>{children}</View>\n </View>\n </KeyboardAvoidingView>\n </View>\n </TouchableWithoutFeedback>\n </Modal>\n </UIThemeProvider>\n </Modal>\n </>\n );\n};\n","import { View, Text } from \"react-native\";\nimport React from \"react\";\nimport { ScaledSheet } from \"react-native-size-matters\";\nimport { GridItemProps, GridProps } from \"../types\";\n\nexport const GridItem: React.FC<GridItemProps> = ({\n children,\n col = 2,\n alignItems,\n spacing = 1,\n style = {},\n}) => {\n const styles = ScaledSheet.create({\n gridItem: {\n width: 100 / col + \"%\",\n padding: spacing * 10 + \"@ms\",\n alignItems: alignItems,\n },\n });\n return <View children={children} style={[styles.gridItem, style]} />;\n};\nexport const Grid: React.FC<GridProps> = ({\n children,\n spacing = 1,\n style = {},\n}) => {\n const styles = ScaledSheet.create({\n grid: {\n flexWrap: \"wrap\",\n margin: -spacing * 10 + \"@ms\",\n flexDirection: \"row\",\n },\n });\n return <View children={children} style={[styles.grid, style]} />;\n};\n","import { Ionicons } from \"@expo/vector-icons\";\nimport React, { useEffect, useState } from \"react\";\nimport { Alert, TouchableOpacity, View } from \"react-native\";\nimport { ListItem } from \"./List\";\nimport TextField from \"./TextField\";\n\nimport * as Location from \"expo-location\";\nimport { ScaledSheet } from \"react-native-size-matters\";\nimport { useColors } from \"../hooks\";\nimport { LocatorProps } from \"../types\";\n\nimport { getConfig } from \"../config/KeyManager\";\nimport Typography from \"./Typography\";\n\nexport type predictionType = {\n id: string;\n description: string;\n};\nexport const getPredictionsFromCoords = async (coords: {\n latitude: number;\n longitude: number;\n}) => {\n const { GOOGLE_MAP_API_KEY } = getConfig();\n\n if (!GOOGLE_MAP_API_KEY)\n console.error(\n \"Google map api key needs to be set to use this component \\nMake sure to run initialize() with a valid google map api key\"\n );\n if (!coords) return [];\n const res = await (\n await fetch(\n `https://maps.googleapis.com/maps/api/geocode/json?radius=200&latlng=${coords.latitude},${coords.longitude}&key=${GOOGLE_MAP_API_KEY}`\n )\n ).json();\n\n const p = [];\n\n for (let key in res.results) {\n const { formatted_address: description, place_id } = res.results[key];\n p.push({\n description,\n id: place_id,\n latLng: { lst: coords.latitude, lng: coords.longitude },\n });\n }\n\n return p;\n};\n\nexport const getPredictionsFromQuery = async (\n query: string,\n country: string\n) => {\n const { GOOGLE_MAP_API_KEY } = getConfig();\n const endpoint = `https://maps.googleapis.com/maps/api/place/autocomplete/json?input=${query}&components=country:${country}&radius=20000&key=${GOOGLE_MAP_API_KEY}`;\n const res = await (await fetch(endpoint)).json();\n\n const p = [];\n for (let key in res.predictions) {\n const { description, place_id } = res.predictions[key];\n p.push({\n description,\n id: place_id,\n });\n }\n return p;\n};\n\nexport const getLocationFromPlaceId = async (\n place_id: string\n): Promise<{\n formatted_address: string;\n geometry: {\n location: {\n lat: number;\n lng: number;\n };\n };\n}> => {\n const { GOOGLE_MAP_API_KEY } = getConfig();\n const res = await (\n await fetch(\n `https://maps.googleapis.com/maps/api/place/details/json?place_id=${place_id}&fields=formatted_address%2Cgeometry&key=${GOOGLE_MAP_API_KEY}`\n )\n ).json();\n return res.result;\n};\n\nexport const Locator: React.FC<LocatorProps> = ({\n variant = \"contained\",\n onLocationSelected,\n label,\n error,\n location = {\n description: null,\n },\n renderInput,\n gutterBottom = 0,\n helperText,\n float = true,\n country = \"ng\",\n}) => {\n const { GOOGLE_MAP_API_KEY } = getConfig();\n\n const [changed, setChanged] = useState(false);\n const [value, setValue] = useState(\"\");\n const [prediction, setPrediction] = useState<predictionType[]>([]);\n const colors = useColors();\n const styles: any = ScaledSheet.create({\n list: {\n backgroundColor: colors.white[2],\n elevation: 10,\n shadowColor: \"#000\",\n shadowOpacity: 0.1,\n shadowRadius: float ? 15 : 0,\n shadowOffset: {\n height: 10,\n },\n borderRadius: 10,\n marginBottom: 10,\n width: \"100%\",\n zIndex: 20,\n marginTop: float ? 2 : \"15@ms\",\n top: float ? \"100%\" : undefined,\n position: float ? \"absolute\" : \"relative\",\n },\n });\n const search = async (query: string) => {\n const predictions = await getPredictionsFromQuery(query, country);\n setPrediction(predictions);\n };\n\n const locateMe = () => {\n // Alert.alert(\n // \"Use my location\",\n // \"Auto fill this input with my current location\",\n // [{ text: \"Cancel\" }, { text: \"Use Location\", onPress: () => getLoc() }]\n // );\n const getLoc = async () => {\n const { status } = await Location.requestForegroundPermissionsAsync();\n if (status !== \"granted\")\n return Alert.alert(\n \"Error\",\n \"Permission to access location was denied! \"\n );\n try {\n let { coords } = await Location.getCurrentPositionAsync({\n accuracy: Location.LocationAccuracy.High,\n });\n const p = await getPredictionsFromCoords(coords);\n setPrediction(p);\n } catch (err) {\n console.log(err);\n Alert.alert(\n \"Can't access your location\",\n \"Make sure your location settings are turned on and you are connected to the internet. \"\n );\n }\n };\n getLoc();\n };\n\n const clear = () => {\n setPrediction([]);\n setValue(\"\");\n onLocationSelected(null);\n setChanged(false);\n };\n const locationPressed = async (loc: predictionType) => {\n setValue(loc.description);\n const res = await getLocationFromPlaceId(loc.id);\n onLocationSelected(\n {\n latitude: res.geometry.location.lat,\n longitude: res.geometry.location.lng,\n description: loc.description,\n },\n res?.formatted_address\n );\n setChanged(false);\n setPrediction([]);\n };\n\n useEffect(() => {\n if (!GOOGLE_MAP_API_KEY)\n console.error(\n \"Google map api key needs to be set to use this component \\nMake sure to run initialize() with a valid google map api key\"\n );\n }, [GOOGLE_MAP_API_KEY]);\n\n return (\n <View style={{ zIndex: 10 }}>\n {renderInput ? (\n renderInput({\n onFocus: () => search(value),\n onBlur: () => setPrediction([]),\n value: changed ? value : location?.description || value,\n onChangeText: (val) => {\n setChanged(true);\n setValue(val);\n search(val);\n },\n clear,\n locateMe,\n })\n ) : (\n <TextField\n label={label}\n onChangeText={(val) => {\n setChanged(true);\n setValue(val);\n search(val);\n }}\n onBlur={() => {\n setPrediction([]);\n }}\n onFocus={() => {\n search(value);\n }}\n value={changed ? value : location?.description || value}\n gutterBottom={gutterBottom}\n error={error}\n helperText={helperText}\n variant={variant}\n end={\n <View style={{ flexDirection: \"row\" }}>\n <TouchableOpacity onPress={locateMe} style={{ marginRight: 10 }}>\n <Ionicons\n color={colors.primary.main}\n size={18}\n name=\"location\"\n />\n </TouchableOpacity>\n <TouchableOpacity onPress={clear}>\n <Ionicons color={colors.dark.main} size={18} name=\"close\" />\n </TouchableOpacity>\n </View>\n }\n />\n )}\n\n {prediction.length > 0 && (\n <View style={styles.list}>\n {prediction.map(\n (cur, i) =>\n i < 5 && (\n <ListItem\n divider={i < prediction.length - 1}\n key={cur.id}\n link\n onPress={() => locationPressed(cur)}\n >\n <Ionicons\n name=\"location-outline\"\n style={{ marginRight: 10 }}\n size={16}\n color={colors.textSecondary.main}\n />\n <Typography style={{ flex: 1 }}>{cur.description}</Typography>\n </ListItem>\n )\n )}\n </View>\n )}\n </View>\n );\n};\n","import { MaterialIcons } from \"@expo/vector-icons\";\nimport React from \"react\";\nimport { TouchableOpacity, View } from \"react-native\";\nimport { ScaledSheet } from \"react-native-size-matters\";\nimport { useColors } from \"../hooks\";\nimport { ListItemProps, ListItemTextProps, ListProps } from \"../types\";\nimport Typography from \"./Typography\";\n\nexport const ListItemText: React.FC<ListItemTextProps> = ({\n primary,\n divider,\n primaryProps = {},\n secondaryProps = {},\n secondary,\n style = {},\n}) => {\n const colors = useColors();\n const styles = ScaledSheet.create({\n container: {\n borderBottomColor: colors.white[2],\n borderBottomWidth: divider ? 1 : 0,\n paddingVertical: 0,\n flexGrow: 1,\n ...style,\n },\n });\n return (\n <View style={styles.container}>\n {primary && (\n <Typography\n style={{ alignItems: \"center\" }}\n variant=\"body1\"\n gutterBottom={2}\n {...primaryProps}\n >\n {primary}\n </Typography>\n )}\n {secondary && (\n <Typography variant=\"body2\" color=\"textSecondary\" {...secondaryProps}>\n {secondary}\n </Typography>\n )}\n </View>\n );\n};\nexport const ListItem: React.FC<ListItemProps> = ({\n link = false,\n divider = false,\n onPress,\n index = 1,\n style = {},\n children,\n}) => {\n const colors = useColors();\n\n const styles: any = ScaledSheet.create({\n root: {\n flexDirection: \"row\",\n alignItems: \"center\",\n paddingHorizontal: \"10@s\",\n borderBottomColor: colors.white[2],\n borderBottomWidth: divider ? 1 : 0,\n paddingVertical: \"10@vs\",\n },\n });\n return (\n <View\n\n // layout={Layout.springify()}\n // exiting={SlideOutDown.delay(index * 100)}\n // entering={SlideInUp.delay(index * 100)}\n >\n <TouchableOpacity disabled={Boolean(!onPress)} onPress={onPress}>\n <View style={{ ...styles.root, ...style }}>\n {children}\n {link && (\n <MaterialIcons\n color={colors.white[5]}\n style={{ marginLeft: \"auto\" }}\n name=\"arrow-forward-ios\"\n size={15}\n />\n )}\n </View>\n </TouchableOpacity>\n </View>\n );\n};\nexport const List: React.FC<ListProps> = ({ style = {}, children }) => {\n const styles = ScaledSheet.create({\n root: {\n flex: 1,\n paddingHorizontal: \"20@ms\",\n ...style,\n },\n });\n return <View style={styles.root}>{children}</View>;\n};\n","import { Ionicons, MaterialIcons } from \"@expo/vector-icons\";\nimport React, { useRef, useState } from \"react\";\nimport { Animated, TextInput, TouchableOpacity, View } from \"react-native\";\nimport {\n ScaledSheet,\n moderateScale,\n ms,\n verticalScale,\n} from \"react-native-size-matters\";\nimport { getConfig } from \"../config/KeyManager\";\nimport { useColors } from \"../hooks\";\nimport { TextFieldProps } from \"../types\";\nimport SelectMenu from \"./SelectMenu\";\nimport Typography from \"./Typography\";\n\nconst TextField: React.FC<TextFieldProps> = ({\n label,\n keyboardType,\n variant,\n color = \"primary\",\n value,\n type,\n helperText,\n onChangeText,\n onSubmitEditing = () => {},\n onFocus = () => {},\n onBlur = () => {},\n error,\n start,\n size = \"normal\",\n rounded,\n disabled = false,\n style = {},\n inputStyles = {},\n gutterBottom = 0,\n end,\n options,\n ...props\n}) => {\n const colors = useColors();\n const [focused, setFocused] = useState(false);\n const height =\n moderateScale(variant === \"text\" ? 50 : 45) *\n (size === \"large\" ? 1.2 : size === \"small\" ? 0.8 : 1);\n\n const labelAnim = useRef(\n new Animated.Value(height / moderateScale(variant === \"text\" ? 2.5 : 3.2))\n ).current;\n\n React.useEffect(() => {\n if (focused || value) {\n Animated.timing(labelAnim, {\n toValue: verticalScale(variant === \"text\" ? 2 : 4),\n duration: 300,\n useNativeDriver: false,\n }).start();\n } else {\n Animated.timing(labelAnim, {\n toValue: height / moderateScale(variant === \"text\" ? 2.5 : 3.2),\n duration: 300,\n useNativeDriver: false,\n }).start();\n }\n }, [focused, value]);\n const styles: any = ScaledSheet.create({\n root: {\n marginBottom: gutterBottom + \"@vs\",\n width: \"100%\",\n ...style,\n },\n container: {\n height: height,\n overflow: \"hidden\",\n\n backgroundColor:\n variant === \"outlined\" || variant === \"text\"\n ? \"#fff0\"\n : focused\n ? colors.white[3]\n : colors.white[4],\n flexDirection: \"row\",\n borderColor: error\n ? colors.error.main\n : focused\n ? colors[color].main\n : colors.textSecondary.main,\n borderWidth: error ? 1 : variant === \"outlined\" ? (focused ? 2 : 0.5) : 0,\n borderBottomWidth: variant === \"text\" ? 0.5 : undefined,\n width: \"100%\",\n borderRadius: variant === \"text\" ? 0 : rounded ? 30 : 7,\n alignItems: \"center\",\n ...inputStyles,\n },\n input: {\n fontSize: \"14@s\