Quellcode durchsuchen

Merge branch 'develop' of https://git.nibgat.space/nibgat-community/ncore-ui-kit-mobile

lfabl vor 1 Monat
Ursprung
Commit
e8a6d785d9

+ 39 - 9
example/src/pages/home/index.tsx

@@ -17,9 +17,11 @@ import {
     PageContainer,
     TextAreaInput,
     BottomSheet,
+    RadioButton,
     TextInput,
     SelectBox,
     CheckBox,
+    RowCard,
     Button,
     Dialog,
     Text
@@ -32,6 +34,7 @@ import type {
 } from "@react-navigation/native-stack";
 import type RootStackParamList from "../../navigation/type";
 import {
+    ChevronRight as ChevronRightIcon,
     HomeIcon
 } from "lucide-react-native";
 
@@ -212,6 +215,11 @@ const Home = () => {
         setIsDialogActive
     ] = useState(false);
 
+    const [
+        isRadioActive,
+        setIsRadioActive
+    ] = useState(false);
+
     return <PageContainer
         isScrollable={true}
         scrollViewStyle={stylesheet.container}
@@ -221,6 +229,37 @@ const Home = () => {
             }
         }}
     >
+        <RowCard
+            title="Merhaba"
+            icon={({
+                color
+            }) => <HomeIcon
+                color={colors.content.icon[color]}
+            />}
+            rightIcon={({
+                color
+            }) => <ChevronRightIcon
+                color={colors.content.icon[color]}
+            />}
+        />
+        <RadioButton
+            isChecked={isRadioActive}
+            title="sadfasfsafasf"
+            isDisabled={false}
+            subTitle="asfgsaf"
+            onPress={() => {
+                setIsRadioActive(!isRadioActive);
+            }}
+        />
+        <CheckBox
+            isChecked={isCheckboxActive}
+            title="sadfasfsafasf"
+            isDisabled={false}
+            subTitle="asfgsaf"
+            onPress={() => {
+                setIsCheckboxActive(isCheckboxActive === "checked" ? null : isCheckboxActive === null ? "partially" : "checked");
+            }}
+        />
         <TextAreaInput
             isUpdateOnRealtime={true}
             spreadBehaviour="stretch"
@@ -257,15 +296,6 @@ const Home = () => {
                 console.log("GELMİŞEEEE:", props);
             }}
         />
-        <CheckBox
-            isChecked={isCheckboxActive}
-            title="sadfasfsafasf"
-            isDisabled={false}
-            subTitle="asfgsaf"
-            onPress={() => {
-                setIsCheckboxActive(isCheckboxActive === "checked" ? null : isCheckboxActive === null ? "partially" : "checked");
-            }}
-        />
         <TextInput
             variant="hidden"
             placeholder="dsagdsag"

+ 7 - 0
src/components/button/stylesheet.ts

@@ -275,6 +275,13 @@ export const useStyles = ({
         }
     }
 
+    if(icon && !title) {
+        styles.container.paddingBottom = currentSize.paddingVertical;
+        styles.container.paddingRight = currentSize.paddingVertical;
+        styles.container.paddingLeft = currentSize.paddingVertical;
+        styles.container.paddingTop = currentSize.paddingVertical;
+    }
+
     if(isCustomPadding) {
         delete styles.container.paddingBottom;
         delete styles.container.paddingRight;

+ 16 - 0
src/components/index.ts

@@ -34,6 +34,10 @@ export {
     default as TextInput
 } from "./textInput";
 
+export type {
+    ITextInputRef
+} from "./textInput/type";
+
 export {
     default as SelectBox
 } from "./selectBox";
@@ -65,3 +69,15 @@ export {
 export {
     default as TextAreaInput
 } from "./textAreaInput";
+
+export type {
+    ITextAreaInputRef
+} from "./textAreaInput/type";
+
+export {
+    default as RadioButton
+} from "./radioButton";
+
+export {
+    default as RowCard
+} from "./rowCard";

+ 260 - 0
src/components/radioButton/index.tsx

@@ -0,0 +1,260 @@
+import {
+    type FC
+} from "react";
+import {
+    TouchableOpacity,
+    View
+} from "react-native";
+import type IRadioButtonProps from "./type";
+import stylesheet, {
+    getRadioButtonType,
+    useStyles
+} from "./stylesheet";
+import {
+    NCoreUIKitLocalize,
+    NCoreUIKitTheme
+} from "../../core/hooks";
+import type ITextProps from "../text/type";
+import Loading from "../loading";
+import Text from "../text";
+
+const RadioButton: FC<IRadioButtonProps> = ({
+    displayBehaviourWhileLoading = "disabled",
+    spreadBehaviour = "baseline",
+    isOptional = false,
+    isDisabled = false,
+    type = "neutral",
+    isFlip = false,
+    customLocalize,
+    subTitleStyle,
+    optionalText,
+    customTheme,
+    titleStyle,
+    isChecked,
+    isLoading,
+    subTitle,
+    onPress,
+    title,
+    style,
+    ...props
+}) => {
+    const {
+        inlineSpaces,
+        radiuses,
+        borders,
+        colors,
+        spaces
+    } = NCoreUIKitTheme.useContext(customTheme);
+
+    const {
+        localize
+    } = NCoreUIKitLocalize.useContext(customLocalize);
+
+    const currentType = getRadioButtonType({
+        type
+    });
+
+    const RADIO_INDICATOR_SIZE = 16;
+
+    const {
+        indicatorContainer: indicatorContainerDynamicStyle,
+        contentContainer: contentContainerDynamicStyle,
+        titleContainer: titleContainerDynamicStyle,
+        optionalText: optionalTextDynamicStyle,
+        container: containerDynamicStyle,
+        indicator: indicatorDynamicStyle,
+        subTitle: subTitleDynamicStyle,
+        loading: loadingDynamicStyle,
+        overlay: overlayDynamicStyle,
+        title: titleDynamicStyle
+    } = useStyles({
+        displayBehaviourWhileLoading,
+        RADIO_INDICATOR_SIZE,
+        spreadBehaviour,
+        inlineSpaces,
+        currentType,
+        isDisabled,
+        isChecked,
+        isLoading,
+        radiuses,
+        borders,
+        isFlip,
+        colors,
+        spaces,
+        type
+    });
+
+    const titleProps: ITextProps = {
+        color: currentType.titleColor,
+    };
+
+    const subTitleProps: ITextProps = {
+        color: currentType.subTitleColor,
+    };
+
+    const indicatorIconProps: {
+        color: keyof NCoreUIKit.IconContentColors;
+        customColor?: string;
+    } = {
+        color: currentType.indicatorColor
+    };
+
+    if (isDisabled || isLoading) {
+        const stateType = type === "danger" ? "error" : type;
+
+        subTitleProps.customColor = colors.system.state.content.disabled[stateType];
+        titleProps.customColor = colors.system.state.content.disabled[stateType];
+
+        if(isChecked && stateType === "neutral") {
+            indicatorIconProps.customColor = colors.system.state.border.disabled.primary;
+        } else {
+            indicatorIconProps.customColor = colors.system.state.border.disabled[stateType];
+        }
+    }
+
+    const renderOptionalText = () => {
+        if(!isOptional && !optionalText) {
+            return null;
+        }
+
+        return <Text
+            variant="labelLargeSize"
+            color={titleProps.color}
+            style={[
+                optionalTextDynamicStyle
+            ]}
+            {...titleProps}
+        >
+            ( {isOptional ? localize("is-optional") : optionalText} )
+        </Text>;
+    };
+
+    const renderTitle = () => {
+        if (!title) {
+            return null;
+        }
+
+        return <View
+            style={[
+                stylesheet.titleContainer,
+                titleContainerDynamicStyle
+            ]}
+        >
+            <Text
+                variant="bodyMediumSize"
+                style={[
+                    titleStyle,
+                    stylesheet.title,
+                    titleDynamicStyle
+                ]}
+                {...titleProps}
+            >
+                {title}
+            </Text>
+            {renderOptionalText()}
+        </View>;
+    };
+
+    const renderIndicator = () => {
+        if(!isChecked) {
+            return <View
+                style={[
+                    indicatorDynamicStyle,
+                    {
+                        backgroundColor: "transparent"
+                    }
+                ]}
+            />;
+        }
+
+        return <View
+            style={[
+                stylesheet.indicator,
+                indicatorDynamicStyle
+            ]}
+        />;
+    };
+
+    const renderIndicatorContainer = () => {
+        if (isLoading) {
+            return <Loading
+                style={[
+                    loadingDynamicStyle
+                ]}
+            />;
+        }
+
+        return <View
+            style={[
+                stylesheet.indicatorContainer,
+                indicatorContainerDynamicStyle
+            ]}
+        >
+            {renderIndicator()}
+
+            {renderOverlay()}
+        </View>;
+    };
+
+    const renderOverlay = () => {
+        return <View
+            style={[
+                stylesheet.overlay,
+                overlayDynamicStyle
+            ]}
+        />;
+    };
+
+    const renderSubtitle = () => {
+        if(!subTitle) {
+            return null;
+        }
+
+        return <Text
+            {...subTitleProps}
+            style={[
+                subTitleStyle,
+                stylesheet.subTitle,
+                subTitleDynamicStyle
+            ]}
+        >
+            {subTitle}
+        </Text>;
+    };
+
+    const renderContent = () => {
+        if(!title) {
+            return null;
+        }
+
+        return <View
+            style={[
+                stylesheet.contentContainer,
+                contentContainerDynamicStyle
+            ]}
+        >
+            {renderTitle()}
+            {renderSubtitle()}
+        </View>;
+    };
+
+    return (
+        <TouchableOpacity
+            {...props}
+            onPress={isDisabled || isLoading ? () => null : onPress ? onPress : undefined}
+            disabled={isDisabled || isLoading || !onPress}
+            style={[
+                style,
+                stylesheet.container,
+                containerDynamicStyle
+            ]}
+        >
+            {isFlip ? null : renderIndicatorContainer()}
+
+            {renderContent()}
+
+            {isFlip ? renderIndicatorContainer() : null}
+        </TouchableOpacity>
+    );
+};
+export default RadioButton;

+ 233 - 0
src/components/radioButton/stylesheet.ts

@@ -0,0 +1,233 @@
+import {
+    type TextStyle,
+    type ViewStyle,
+    StyleSheet
+} from "react-native";
+import {
+    type RadioButtonDynamicStyleType,
+    type RadioButtonTypeConstantType,
+    type RadioButtonTypes,
+    type RadioButtonType
+} from "./type";
+import type {
+    Mutable
+} from "../../types";
+
+export const RADIO_BUTTON_TYPE_STYLES: Record<
+    RadioButtonType,
+    {
+        containerColor: keyof NCoreUIKit.ContainerContentColors;
+        indicatorColor: keyof NCoreUIKit.IconContentColors;
+        subTitleColor: keyof NCoreUIKit.TextContentColors;
+        borderColor: keyof NCoreUIKit.BorderContentColors;
+        titleColor: keyof NCoreUIKit.TextContentColors;
+    }
+> = {
+    primary: {
+        indicatorColor: "emphasized",
+        borderColor: "emphasized",
+        containerColor: "mid",
+        subTitleColor: "low",
+        titleColor: "mid"
+    },
+    danger: {
+        subTitleColor: "dangerLow",
+        indicatorColor: "danger",
+        containerColor: "danger",
+        borderColor: "danger",
+        titleColor: "danger"
+    },
+    success: {
+        subTitleColor: "successLow",
+        indicatorColor: "success",
+        containerColor: "success",
+        borderColor: "success",
+        titleColor: "success"
+    },
+    warning: {
+        subTitleColor: "warningLow",
+        indicatorColor: "warning",
+        containerColor: "warning",
+        borderColor: "warning",
+        titleColor: "warning"
+    },
+    info: {
+        subTitleColor: "infoLow",
+        indicatorColor: "info",
+        containerColor: "info",
+        borderColor: "info",
+        titleColor: "info"
+    },
+    neutral: {
+        indicatorColor: "emphasized",
+        containerColor: "mid",
+        borderColor: "subtle",
+        subTitleColor: "low",
+        titleColor: "mid"
+    }
+};
+
+export const getRadioButtonType = ({
+    type
+}: RadioButtonTypeConstantType): RadioButtonTypes => {
+    const currentType = RADIO_BUTTON_TYPE_STYLES[type];
+
+    return currentType;
+};
+
+const stylesheet = StyleSheet.create({
+    container: {
+        backgroundColor: "transparent",
+        borderColor: "transparent",
+        flexDirection: "row",
+        borderStyle: "solid",
+        alignItems: "center",
+        display: "flex"
+    },
+    indicatorContainer: {
+        position: "relative"
+    },
+    indicator: {
+        borderStyle: "solid"
+    },
+    contentContainer: {
+        justifyContent: "center",
+        flexDirection: "column"
+    },
+    titleContainer: {
+        justifyContent: "flex-start",
+        flexDirection: "row",
+        alignItems: "center"
+    },
+    title: {
+        textAlign: "left",
+        margin: 0
+    },
+    subTitle: {
+        textAlign: "left"
+    },
+    loading: {},
+    overlay: {
+        position: "absolute",
+        display: "none",
+        zIndex: 999,
+        bottom: -2,
+        right: -2,
+        left: -2,
+        top: -2
+    }
+});
+
+export const useStyles = ({
+    displayBehaviourWhileLoading,
+    RADIO_INDICATOR_SIZE,
+    spreadBehaviour,
+    inlineSpaces,
+    currentType,
+    isDisabled,
+    isLoading,
+    isChecked,
+    radiuses,
+    borders,
+    colors,
+    isFlip,
+    spaces,
+    type
+}: RadioButtonDynamicStyleType) => {
+    const styleType = type === "danger" ? "error" : type;
+
+    const styles = {
+        container: {
+            padding: spaces.spacingSm
+        } as Mutable<ViewStyle>,
+        indicatorContainer: {
+            borderRadius: (RADIO_INDICATOR_SIZE + (spaces.spacingXs * 2) + (borders.line * 2)) / 2,
+            backgroundColor: colors.content.container[currentType.containerColor],
+            borderColor: colors.content.border[currentType.borderColor],
+            borderWidth: borders.line,
+            padding: spaces.spacingXs
+        } as Mutable<ViewStyle>,
+        indicator: {
+            backgroundColor: colors.content.icon[currentType.indicatorColor],
+            borderRadius: RADIO_INDICATOR_SIZE / 2,
+            height: RADIO_INDICATOR_SIZE,
+            width: RADIO_INDICATOR_SIZE
+        } as Mutable<ViewStyle>,
+        contentContainer: {
+            marginLeft: spaces.spacingSm
+        } as Mutable<ViewStyle>,
+        titleContainer: {
+
+        } as Mutable<ViewStyle>,
+        title: {
+
+        } as Mutable<TextStyle>,
+        subTitle: {
+
+        } as Mutable<TextStyle>,
+        loading: {
+        } as Mutable<ViewStyle>,
+        overlay: {
+            borderRadius: radiuses.actions
+        } as Mutable<ViewStyle>,
+        optionalText: {
+            marginLeft: inlineSpaces.subTitle
+        } as Mutable<TextStyle>
+    };
+
+    if(styleType === "neutral") {
+        styles.indicatorContainer.borderColor = colors.content.border.default;
+    }
+
+    if (isLoading) {
+        if (displayBehaviourWhileLoading === "disabled") {
+            styles.indicatorContainer.borderColor = colors.system.state.overlay.disabled[styleType];
+
+            styles.overlay.backgroundColor = colors.system.state.overlay.disabled[styleType];
+            styles.overlay.display = "flex";
+        }
+    }
+
+    if (isFlip) {
+        styles.contentContainer.marginRight = spaces.spacingSm;
+        styles.titleContainer.justifyContent = "flex-end";
+        styles.contentContainer.marginLeft = 0;
+        styles.subTitle.textAlign = "right";
+        styles.title.textAlign = "right";
+    }
+
+    if (spreadBehaviour === "baseline") {
+        styles.container.alignSelf = spreadBehaviour;
+        styles.container.width = "auto";
+    } else if (spreadBehaviour === "stretch") {
+        styles.contentContainer.alignSelf = spreadBehaviour;
+        styles.container.alignSelf = spreadBehaviour;
+        styles.container.justifyContent = "center";
+        styles.contentContainer.flexShrink = 1;
+        styles.contentContainer.width = "100%";
+        styles.container.flexShrink = 1;
+        styles.container.width = "100%";
+    }
+
+    if(isChecked) {
+        if(styleType === "neutral") {
+            styles.indicatorContainer.backgroundColor = colors.content.container.selected;
+            styles.indicatorContainer.borderColor = colors.content.border.emphasized;
+        }
+    }
+
+    if (isDisabled) {
+        if(styleType === "neutral" && isChecked) {
+            styles.indicatorContainer.backgroundColor = colors.system.state.border.disabled.primary;
+            styles.indicatorContainer.borderColor = colors.system.state.border.disabled.primary;
+        } else {
+            styles.indicatorContainer.borderColor = colors.system.state.border.disabled[styleType];
+        }
+
+        styles.overlay.backgroundColor = colors.system.state.overlay.disabled[styleType];
+        styles.overlay.display = "flex";
+    }
+
+    return styles;
+};
+export default stylesheet;

+ 70 - 0
src/components/radioButton/type.ts

@@ -0,0 +1,70 @@
+import {
+    type ViewStyle,
+    type StyleProp,
+    type TextStyle
+} from "react-native";
+
+export type RadioButtonDynamicStyleType = {
+    displayBehaviourWhileLoading?: RadioButtonDisplayBehaviourWhileLoading;
+    inlineSpaces: NCoreUIKit.ActivePalette["inlineSpaces"];
+    radiuses: NCoreUIKit.ActivePalette["radiuses"];
+    spreadBehaviour?: RadioButtonSpreadBehaviour;
+    spaces: NCoreUIKit.ActivePalette["spaces"];
+    colors: NCoreUIKit.ActivePalette["colors"];
+    currentType: RadioButtonTypes;
+    RADIO_INDICATOR_SIZE: number;
+    borders: NCoreUIKit.Borders;
+    type: RadioButtonType;
+    isDisabled?: boolean;
+    isLoading?: boolean;
+    isChecked?: boolean;
+    isFlip?: boolean;
+};
+
+export type RadioButtonTypes = {
+    containerColor: keyof NCoreUIKit.ContainerContentColors;
+    indicatorColor: keyof NCoreUIKit.IconContentColors;
+    subTitleColor: keyof NCoreUIKit.TextContentColors;
+    borderColor: keyof NCoreUIKit.BorderContentColors;
+    titleColor: keyof NCoreUIKit.TextContentColors;
+};
+
+export type RadioButtonTypeConstantType = {
+    type: RadioButtonType;
+};
+
+export type RadioButtonType = "primary" | "danger" | "warning" | "neutral" | "success" | "info";
+
+export type RadioButtonDisplayBehaviourWhileLoading = "none" | "disabled";
+
+export type RadioButtonSpreadBehaviour = "baseline" | "stretch" | "free";
+
+interface IRadioButtonProps {
+    displayBehaviourWhileLoading?: RadioButtonDisplayBehaviourWhileLoading;
+    subTitleStyle?: StyleProp<TextStyle>[] | StyleProp<TextStyle>;
+    titleStyle?: StyleProp<TextStyle>[] | StyleProp<TextStyle>;
+    style?: StyleProp<ViewStyle>[] | StyleProp<ViewStyle>;
+    customTheme?: {
+        gapPropagation?: NCoreUIKit.GapPropagationKey;
+        sharpness?: NCoreUIKit.SharpnessKey;
+        paletteKey?: NCoreUIKit.PaletteKey;
+        themeKey?: NCoreUIKit.ThemeKey;
+    };
+    spreadBehaviour?: RadioButtonSpreadBehaviour;
+    customLocalize?: {
+        activeLocale?: NCoreUIKit.LocaleKey;
+    };
+    type?: RadioButtonType;
+    optionalText?: string;
+    isDisabled?: boolean;
+    isOptional?: boolean;
+    onPress?: () => void;
+    isLoading?: boolean;
+    isChecked?: boolean;
+    subTitle?: string;
+    isFlip?: boolean;
+    title?: string;
+}
+export type {
+    IRadioButtonProps as default
+};

+ 219 - 0
src/components/rowCard/index.tsx

@@ -0,0 +1,219 @@
+import {
+    type FC
+} from "react";
+import {
+    TouchableOpacity,
+    View
+} from "react-native";
+import type IRowCardProps from "./type";
+import stylesheet, {
+    useStyles
+} from "./stylesheet";
+import {
+    NCoreUIKitTheme
+} from "../../core/hooks";
+import Text from "../text";
+
+const RowCard: FC<IRowCardProps> = ({
+    rightContentContainerStyle,
+    rightIcon: CustomRightIcon,
+    leftContentContainerStyle,
+    type = "first-based",
+    rightContainerStyle,
+    rightSubTitleStyle,
+    leftContainerStyle,
+    leftSubTitleStyle,
+    icon: CustomIcon,
+    rightTitleStyle,
+    rightIconStyle,
+    leftTitleStyle,
+    rightSubTitle,
+    customTheme,
+    rightTitle,
+    iconStyle,
+    subTitle,
+    onPress,
+    style,
+    title
+}) => {
+    const {
+        radiuses,
+        colors,
+        spaces
+    } = NCoreUIKitTheme.useContext(customTheme);
+
+    const {
+        rightIconContainer: rightIconContainerDynamicStyle,
+        rightContainer: rightContainerDynamicStyle,
+        leftContainer: leftContainerDynamicStyle,
+        iconContainer: iconContainerDynamicStyle,
+        rightSubTitle: rightSubTitleDynamicStyle,
+        rightTitle: rightTitleDynamicStyle,
+        container: containerDynamicStyle,
+        subTitle: subTitleDynamicStyle,
+        title: titleDynamicStyle
+    } = useStyles({
+        radiuses,
+        subTitle,
+        spaces,
+        colors,
+        type
+    });
+
+    const renderRightIcon = () => {
+        if(!CustomRightIcon) {
+            return null;
+        }
+
+        return <View
+            style={[
+                rightIconStyle,
+                stylesheet.rightIconContainer,
+                rightIconContainerDynamicStyle
+            ]}
+        >
+            <CustomRightIcon
+                color="default"
+                size={18}
+            />
+        </View>;
+    };
+
+    const renderLeftIcon = () => {
+        if(!CustomIcon) {
+            return null;
+        }
+
+        return <View
+            style={[
+                iconStyle,
+                stylesheet.iconContainer,
+                iconContainerDynamicStyle
+            ]}
+        >
+            <CustomIcon
+                color="default"
+                size={18}
+            />
+        </View>;
+    };
+
+    const renderLeftSubTitle = () => {
+        if(!subTitle) {
+            return null;
+        }
+
+        return <Text
+            variant="labelLargeSize"
+            color="low"
+            style={[
+                leftSubTitleStyle,
+                stylesheet.subTitle,
+                subTitleDynamicStyle
+            ]}
+        >
+            {subTitle}
+        </Text>;
+    };
+
+    const renderLeftContent = () => {
+        return <View
+            style={[
+                leftContentContainerStyle
+            ]}
+        >
+            <Text
+                variant="labelLargeSize"
+                style={[
+                    leftTitleStyle,
+                    stylesheet.title,
+                    titleDynamicStyle
+                ]}
+            >
+                {title}
+            </Text>
+            {renderLeftSubTitle()}
+        </View>;
+    };
+
+    const renderLeft = () => {
+        return <View
+            style={[
+                leftContainerStyle,
+                stylesheet.leftContainer,
+                leftContainerDynamicStyle
+            ]}
+        >
+            {renderLeftContent()}
+        </View>;
+    };
+
+    const renderRightSubTitle = () => {
+        if(!rightSubTitle) {
+            return null;
+        }
+
+        return <Text
+            variant="labelLargeSize"
+            color="low"
+            style={[
+                rightSubTitleStyle,
+                stylesheet.rightSubTitle,
+                rightSubTitleDynamicStyle
+            ]}
+        >
+            {rightSubTitle}
+        </Text>;
+    };
+
+    const renderRightContent = () => {
+        return <View
+            style={[
+                rightContentContainerStyle
+            ]}
+        >
+            <Text
+                variant="labelLargeSize"
+                style={[
+                    rightTitleStyle,
+                    stylesheet.rightTitle,
+                    rightTitleDynamicStyle
+                ]}
+            >
+                {rightTitle}
+            </Text>
+            {renderRightSubTitle()}
+        </View>;
+    };
+
+    const renderRight = () => {
+        return <View
+            style={[
+                rightContainerStyle,
+                stylesheet.rightContainer,
+                rightContainerDynamicStyle
+            ]}
+        >
+            {renderRightContent()}
+        </View>;
+    };
+
+    return <TouchableOpacity
+        style={[
+            style,
+            stylesheet.container,
+            containerDynamicStyle
+        ]}
+        onPress={() => {
+            if(onPress) {
+                onPress();
+            }
+        }}
+    >
+        {renderLeftIcon()}
+        {renderLeft()}
+        {renderRight()}
+        {renderRightIcon()}
+    </TouchableOpacity>;
+};
+export default RowCard;

+ 94 - 0
src/components/rowCard/stylesheet.ts

@@ -0,0 +1,94 @@
+import {
+    type TextStyle,
+    type ViewStyle,
+    StyleSheet
+} from "react-native";
+import type {
+    RowCardDynamicStyleType
+} from "./type";
+import type {
+    Mutable
+} from "../../types";
+
+const stylesheet = StyleSheet.create({
+    container: {
+        flexDirection: "row",
+        alignItems: "center"
+    },
+    iconContainer: {
+        justifyContent: "center",
+        alignItems: "center"
+    },
+    rightIconContainer: {
+
+    },
+    title: {
+        textAlign: "left"
+    },
+    subTitle: {
+        textAlign: "left"
+    },
+    rightContainer: {
+        justifyContent: "flex-end",
+        flexDirection: "row",
+        alignItems: "center"
+    },
+    leftContainer: {
+        justifyContent: "flex-start",
+        flexDirection: "row",
+        alignItems: "center"
+    },
+    rightSubTitle: {
+
+    },
+    rightTitle: {
+
+    }
+});
+
+export const useStyles = ({
+    spaces,
+    colors,
+    type
+}: RowCardDynamicStyleType) => {
+    const styles = {
+        container: {
+            backgroundColor: colors.content.container.mid,
+            padding: spaces.spacingMd
+        } as Mutable<ViewStyle>,
+        title: {
+            textAlign: "left"
+        } as Mutable<TextStyle>,
+        subTitle: {
+            textAlign: "left"
+        } as Mutable<TextStyle>,
+        iconContainer: {
+            paddingHorizontal: spaces.spacingSm
+        } as Mutable<ViewStyle>,
+        rightSubTitle: {
+            textAlign: "right"
+        } as Mutable<TextStyle>,
+        leftContainer: {
+            paddingHorizontal: spaces.spacingSm
+        } as Mutable<ViewStyle>,
+        rightContainer: {
+            paddingHorizontal: spaces.spacingSm
+        } as Mutable<ViewStyle>,
+        rightIconContainer: {
+            paddingHorizontal: spaces.spacingSm
+        } as Mutable<ViewStyle>,
+        rightTitle: {
+            textAlign: "right"
+        } as Mutable<TextStyle>
+    };
+
+    if(type === "evenly") {
+        styles.rightContainer.flex = 1;
+        styles.leftContainer.flex = 1;
+    } else {
+        styles.leftContainer.flex = 1;
+    }
+
+    return styles;
+};
+export default stylesheet;

+ 49 - 0
src/components/rowCard/type.ts

@@ -0,0 +1,49 @@
+import {
+    type StyleProp,
+    type ViewStyle
+} from "react-native";
+import type {
+    NCoreUIKitIcon
+} from "../../types";
+
+export type RowCardDynamicStyleType = {
+    radiuses: NCoreUIKit.ActivePalette["radiuses"];
+    spaces: NCoreUIKit.ActivePalette["spaces"];
+    colors: NCoreUIKit.ActivePalette["colors"];
+    subTitle?: string;
+    type: RowCardType;
+};
+
+export type RowCardType = "first-based" | "evenly";
+
+type IRowCardProps = {
+    rightContentContainerStyle?: StyleProp<ViewStyle>[] | StyleProp<ViewStyle>;
+    leftContentContainerStyle?: StyleProp<ViewStyle>[] | StyleProp<ViewStyle>;
+    rightContainerStyle?: StyleProp<ViewStyle>[] | StyleProp<ViewStyle>;
+    leftContainerStyle?: StyleProp<ViewStyle>[] | StyleProp<ViewStyle>;
+    rightSubTitleStyle?: StyleProp<ViewStyle>[] | StyleProp<ViewStyle>;
+    leftSubTitleStyle?: StyleProp<ViewStyle>[] | StyleProp<ViewStyle>;
+    rightTitleStyle?: StyleProp<ViewStyle>[] | StyleProp<ViewStyle>;
+    leftTitleStyle?: StyleProp<ViewStyle>[] | StyleProp<ViewStyle>;
+    rightIconStyle?: StyleProp<ViewStyle>[] | StyleProp<ViewStyle>;
+    iconStyle?: StyleProp<ViewStyle>[] | StyleProp<ViewStyle>;
+    style?: StyleProp<ViewStyle>[] | StyleProp<ViewStyle>;
+    rightIcon?: NCoreUIKitIcon;
+    rightSubTitle?: string;
+    icon?: NCoreUIKitIcon;
+    onPress?: () => void;
+    rightTitle?: string;
+    type?: RowCardType;
+    subTitle?: string;
+    title: string;
+    customTheme?: {
+        gapPropagation?: NCoreUIKit.GapPropagationKey;
+        sharpness?: NCoreUIKit.SharpnessKey;
+        paletteKey?: NCoreUIKit.PaletteKey;
+        themeKey?: NCoreUIKit.ThemeKey;
+    };
+};
+
+export type {
+    IRowCardProps as default
+};

+ 4 - 0
src/index.tsx

@@ -18,10 +18,12 @@ export {
     TextAreaInput,
     BottomSheet,
     SelectSheet,
+    RadioButton,
     TextInput,
     SelectBox,
     SnackBar,
     CheckBox,
+    RowCard,
     Loading,
     Dialog,
     Button,
@@ -31,7 +33,9 @@ export {
 } from "./components";
 
 export type {
+    ITextAreaInputRef,
     IBottomSheetRef,
+    ITextInputRef,
     IDialogRef,
     IModalRef
 } from "./components";