Bläddra i källkod

Feature: TextAreaInput component added.

lfabl 1 månad sedan
förälder
incheckning
aa0af91f8f

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

@@ -7,20 +7,22 @@ import {
 } from "react-native";
 import stylesheet from "./stylesheet";
 import {
-    type IBottomSheetRef,
+    NCoreUIKitBottomSheet,
     getNCoreUIKitVersion,
+    type IBottomSheetRef,
     NCoreUIKitSnackBar,
     NCoreUIKitDialog,
     NCoreUIKitToast,
     NCoreUIKitTheme,
+    PageContainer,
+    TextAreaInput,
     BottomSheet,
     TextInput,
     SelectBox,
     CheckBox,
     Button,
     Dialog,
-    Text,
-    NCoreUIKitBottomSheet
+    Text
 } from "ncore-ui-kit-mobile";
 import {
     useNavigation
@@ -210,14 +212,29 @@ const Home = () => {
         setIsDialogActive
     ] = useState(false);
 
-    return <View
-        style={[
-            stylesheet.container,
-            {
+    return <PageContainer
+        isScrollable={true}
+        scrollViewStyle={stylesheet.container}
+        scrollViewProps={{
+            contentContainerStyle: {
                 backgroundColor: colors.content.container.default
             }
-        ]}
+        }}
     >
+        <TextAreaInput
+            isUpdateOnRealtime={true}
+            spreadBehaviour="stretch"
+            placeholder="efsdg"
+            maxLength={300}
+            title="Merhaba"
+            type="success"
+            isCleanEnabled={true}
+            icon={({
+                color
+            }) => <HomeIcon
+                color={colors.content.icon[color]}
+            />}
+        />
         <SelectBox
             keyExtractor={(data, index) => `${data.t}-${index}`}
             titleExtractor={(data) => data.t}
@@ -251,6 +268,7 @@ const Home = () => {
         />
         <TextInput
             variant="hidden"
+            placeholder="dsagdsag"
         />
         <Text>Version: v{getNCoreUIKitVersion()}</Text>
         <Button
@@ -470,6 +488,6 @@ const Home = () => {
             <Text>Deneme 123</Text>
             <Text>Deneme 123</Text>
         </BottomSheet>
-    </View>;
+    </PageContainer>;
 };
 export default Home;

+ 4 - 2
example/src/pages/home/stylesheet.ts

@@ -4,9 +4,11 @@ import {
 
 const stylesheet = StyleSheet.create({
     container: {
-        justifyContent: "center",
-        alignItems: "center",
         flex: 1
+    },
+    contentContainer: {
+        justifyContent: "center",
+        alignItems: "center"
     }
 });
 export default stylesheet;

+ 4 - 2
src/components/dialog/index.tsx

@@ -39,6 +39,8 @@ import {
 const Dialog: RefForwardingComponent<IDialogRef, IDialogProps> = ({
     bottomContentContainerStyle,
     contentJustify = "centered",
+    closeAnimationDelay = 100,
+    openAnimationDelay = 100,
     contentContainerStyle,
     bottomContainerStyle,
     headerContainerStyle,
@@ -102,9 +104,9 @@ const Dialog: RefForwardingComponent<IDialogRef, IDialogProps> = ({
     useEffect(() => {
         if(isVisible) {
             Animated.timing(scaleAnim, {
+                duration: openAnimationDelay,
                 useNativeDriver: true,
                 easing: Easing.linear,
-                duration: 350,
                 toValue: 1
             }).start();
         }
@@ -122,9 +124,9 @@ const Dialog: RefForwardingComponent<IDialogRef, IDialogProps> = ({
         id: string;
     }) => void) => {
         Animated.timing(scaleAnim, {
+            duration: closeAnimationDelay,
             useNativeDriver: true,
             easing: Easing.linear,
-            duration: 250,
             toValue: 0
         }).start(({
             finished

+ 2 - 0
src/components/dialog/type.ts

@@ -64,6 +64,8 @@ interface IDialogProps {
     contentJustify?: DialogContentJustify;
     secondaryButtonProps?: DialogButton;
     primaryButtonProps?: DialogButton;
+    closeAnimationDelay?: number;
+    openAnimationDelay?: number;
     headerComponent?: ReactNode;
     bottomComponent?: ReactNode;
     variant?: DialogVariant;

+ 8 - 0
src/components/index.ts

@@ -57,3 +57,11 @@ export {
 export {
     default as Toast
 } from "./toast";
+
+export {
+    default as SnackBar
+} from "./snackBar";
+
+export {
+    default as TextAreaInput
+} from "./textAreaInput";

+ 8 - 6
src/components/modal/index.tsx

@@ -36,7 +36,9 @@ import {
  */
 const Modal: RefForwardingComponent<IModalRef, IModalProps> = ({
     isScaleAnimatedOnlyOpen = true,
+    closeAnimationDelay = 100,
     isDisabledOverlay = false,
+    openAnimationDelay = 100,
     isContentRequired = true,
     isOverlayVisible = true,
     isScaleAnimated = false,
@@ -73,17 +75,17 @@ const Modal: RefForwardingComponent<IModalRef, IModalProps> = ({
         if(isAnimated) {
             if(isScaleAnimated) {
                 Animated.timing(scaleAnim, {
-                    easing: Easing.out(Easing.back(1.5)),
+                    duration: openAnimationDelay,
                     useNativeDriver: true,
-                    duration: 350,
+                    easing: Easing.linear,
                     toValue: 1
                 }).start();
             }
 
             Animated.timing(opacityAnim, {
+                duration: openAnimationDelay,
                 useNativeDriver: true,
                 easing: Easing.linear,
-                duration: 350,
                 toValue: 1
             }).start();
         }
@@ -110,17 +112,17 @@ const Modal: RefForwardingComponent<IModalRef, IModalProps> = ({
         if(isAnimated) {
             if(isScaleAnimated && !isScaleAnimatedOnlyOpen) {
                 Animated.timing(scaleAnim, {
-                    easing: Easing.in(Easing.ease),
+                    duration: closeAnimationDelay,
                     useNativeDriver: true,
-                    duration: 250,
+                    easing: Easing.linear,
                     toValue: 0
                 }).start();
             }
 
             Animated.timing(opacityAnim, {
+                duration: closeAnimationDelay,
                 useNativeDriver: true,
                 easing: Easing.linear,
-                duration: 250,
                 toValue: 0
             }).start(({
                 finished

+ 2 - 0
src/components/modal/type.ts

@@ -32,6 +32,8 @@ export type ModalInternalProps = {
     }) => void;
     alignContent?: ModalAlignContentProp;
     isScaleAnimatedOnlyOpen?: boolean;
+    closeAnimationDelay?: number;
+    openAnimationDelay?: number;
     isDisabledOverlay?: boolean;
     isContentRequired?: boolean;
     isOverlayVisible?: boolean;

+ 2 - 1
src/components/pageContainer/index.tsx

@@ -37,11 +37,12 @@ const PageContainer: FC<IPageContainerProps> = ({
             console.error("Hey!. You make wrong things. If you must be use isScrollable={true}, you must be use scrollViewStyle. Do not use style prop for this case.");
         }
 
-        if(props) {
+        if(Object.keys(props).length) {
             console.error("Hey!. You make wrong things. If you must be use isScrollable={true}, you must be use scrollViewProps. Do not use default view props for this case.");
         }
 
         return <ScrollView
+            keyboardShouldPersistTaps="handled"
             {...scrollViewProps}
             contentContainerStyle={[
                 {

+ 1 - 1
src/components/pageContainer/type.ts

@@ -10,8 +10,8 @@ import type {
 interface IPageContainerProps {
     safeAreaViewBackgroundColor?: keyof NCoreUIKit.ContainerContentColors;
     backgroundColor?: keyof NCoreUIKit.ContainerContentColors;
-    scrollViewStyle?: StyleProp<ScrollViewProps>;
     safeAreaViewStyle?: StyleProp<ViewStyle>;
+    scrollViewStyle?: StyleProp<ViewStyle>;
     scrollViewProps?: ScrollViewProps;
     isWrapSafeareaContext?: boolean;
     style?: StyleProp<ViewStyle>;

+ 3 - 0
src/components/selectBox/index.tsx

@@ -153,6 +153,7 @@ function SelectBox<T>({
         inlineSpaces,
         isSearchable,
         currentType,
+        typography,
         isDisabled,
         radiuses,
         borders,
@@ -736,6 +737,7 @@ function SelectBox<T>({
     const renderValue = () => {
         if(!selectedItems.length) {
             return <Text
+                variant="labelLargeSize"
                 style={[
                     stylesheet.contentText,
                     contentTextDynamicStyle
@@ -746,6 +748,7 @@ function SelectBox<T>({
         }
 
         return <Text
+            variant="labelLargeSize"
             style={[
                 stylesheet.contentText,
                 contentTextDynamicStyle

+ 4 - 0
src/components/snackBar/index.tsx

@@ -41,6 +41,8 @@ const SnackBar: FC<ISnackBarProps> = ({
     autoCloseDelay = 5000,
     isCloseOnPress = true,
     isShowAction = true,
+    isFullWidth = false,
+    isInlineSafeArea,
     icon: CustomIcon,
     type = "neutral",
     customTheme,
@@ -86,7 +88,9 @@ const SnackBar: FC<ISnackBarProps> = ({
         action: actionDynamicStyle,
         title: titleDynamicStyle
     } = useStyles({
+        isInlineSafeArea,
         safeAreaTop: top,
+        isFullWidth,
         currentType,
         radiuses,
         spaces,

+ 12 - 0
src/components/snackBar/stylesheet.ts

@@ -108,6 +108,8 @@ const stylesheet = StyleSheet.create({
 });
 
 export const useStyles = ({
+    isInlineSafeArea,
+    isFullWidth,
     safeAreaTop,
     currentType,
     radiuses,
@@ -147,6 +149,16 @@ export const useStyles = ({
         } as Mutable<ViewStyle>
     };
 
+    if(isFullWidth) {
+        styles.container.width = windowWidth;
+        styles.container.borderRadius = 0;
+    }
+
+    if(isInlineSafeArea) {
+        styles.container.paddingTop = safeAreaTop;
+        styles.container.top = 0;
+    }
+
     return styles;
 };
 export default stylesheet;

+ 4 - 0
src/components/snackBar/type.ts

@@ -13,7 +13,9 @@ export type SnackBarDynamicStyleType = {
     radiuses: NCoreUIKit.ActivePalette["radiuses"];
     spaces: NCoreUIKit.ActivePalette["spaces"];
     colors: NCoreUIKit.ActivePalette["colors"];
+    isInlineSafeArea?: boolean;
     currentType: SnackBarTypes;
+    isFullWidth?: boolean;
     safeAreaTop: number;
     type: SnackBarType;
 };
@@ -50,9 +52,11 @@ export type SnackBarInternalProps = {
     isCloseOnPressActionButton?: boolean;
     closeAnimationDelay?: number;
     openAnimationDelay?: number;
+    isInlineSafeArea?: boolean;
     isCloseOnPress?: boolean;
     autoCloseDelay?: number;
     isShowAction?: boolean;
+    isFullWidth?: boolean;
     icon?: NCoreUIKitIcon;
     children?: ReactNode;
     type?: SnackBarType;

+ 542 - 0
src/components/textAreaInput/index.tsx

@@ -0,0 +1,542 @@
+import {
+    useImperativeHandle,
+    forwardRef,
+    useEffect,
+    useState,
+    useRef
+} from "react";
+import {
+    TextInput as NativeTextInput,
+    TouchableOpacity,
+    Keyboard,
+    View
+} from "react-native";
+import type ITextAreaInputProps from "./type";
+import {
+    type TextAreaInputInstance,
+    type ITextAreaInputRef,
+    type TextAreaInputType
+} from "./type";
+import stylesheet, {
+    getTextAreaInputType,
+    useStyles
+} from "./stylesheet";
+import {
+    NCoreUIKitLocalize,
+    NCoreUIKitTheme
+} from "../../core/hooks";
+import {
+    type RefForwardingComponent
+} from "../../types";
+import type ITextProps from "../text/type";
+import {
+    BadgeQuestionMark as BadgeQuestionMarkIcon,
+    BadgeAlert as BadgeAlertIcon,
+    BadgeCheck as BadgeCheckIcon,
+    BadgeInfo as BadgeInfoIcon,
+    CircleX as CircleXIcon,
+    BadgeX as BadgeXIcon,
+    type LucideIcon
+} from "lucide-react-native";
+import Text from "../text";
+
+const TextInputTypeIcon: Record<Exclude<TextAreaInputType, "default">, LucideIcon> = {
+    "question": BadgeQuestionMarkIcon,
+    "success": BadgeCheckIcon,
+    "warning": BadgeAlertIcon,
+    "info": BadgeInfoIcon,
+    "danger": BadgeXIcon
+};
+
+const TextAreaInput: RefForwardingComponent<ITextAreaInputRef, ITextAreaInputProps> = ({
+    isAutoKeyboardDismissOnBlur = true,
+    rightIcon: RightIconComponentProp,
+    hintTextIcon: HintTextIconProp,
+    spreadBehaviour = "baseline",
+    isShowLengthLimiter = true,
+    isShowHintTextIcon = false,
+    isUpdateOnRealtime = false,
+    icon: IconComponentProp,
+    hintTextContainerStyle,
+    isCleanEnabled = false,
+    contentContainerStyle,
+    subTitle = "Optional",
+    onFocus: onFocusProp,
+    isRequired = false,
+    isDisabled = false,
+    onBlur: onBlurProp,
+    type = "default",
+    rightIconOnPress,
+    maxHeight = 350,
+    customLocalize,
+    rightIconStyle,
+    isShowSubTitle,
+    cleanIconStyle,
+    onChangeText,
+    initialValue,
+    customTheme,
+    placeholder,
+    iconOnPress,
+    isOptional,
+    validation,
+    inputStyle,
+    maxLength,
+    iconStyle,
+    hintText,
+    style,
+    title,
+    ...props
+}, ref) => {
+    const {
+        inlineSpaces,
+        typography,
+        radiuses,
+        borders,
+        spaces,
+        colors
+    } = NCoreUIKitTheme.useContext(customTheme);
+
+    const {
+        localize
+    } = NCoreUIKitLocalize.useContext(customLocalize);
+
+    const currentType = getTextAreaInputType({
+        type
+    });
+
+    const inputRef = useRef<TextAreaInputInstance | null>(null);
+
+    const styleType = type === "default" ? "neutral" : type === "question" ? "neutral" : type === "danger" ? "error" : type;
+
+    const [
+        value,
+        setValue
+    ] = useState(initialValue ? initialValue : "");
+
+    const [
+        isFocused,
+        setIsFocused
+    ] = useState(false);
+
+    const {
+        lengthLimiterContainer: lengthLimiterContainerDynamicStyle,
+        titleContainer: titleContainerDynamicStyle,
+        inputContainer: inputContainerDynamicStyle,
+        hintTextIcon: hintTextIconDynamicStyle,
+        cleanButton: cleanButtonDynamicStyle,
+        rightIcon: rightIconDynamicStyle,
+        container: containerDynamicStyle,
+        hintText: hintTextDynamicStyle,
+        required: requiredDynamicStyle,
+        subTitle: subTitleDynamicStyle,
+        content: contentDynamicStyle,
+        overlay: overlayDynamicStyle,
+        title: titleDynamicStyle,
+        input: inputDynamicStyle,
+        icon: iconDynamicStyle
+    } = useStyles({
+        icon: IconComponentProp ? true : false,
+        spreadBehaviour,
+        inlineSpaces,
+        currentType,
+        isDisabled,
+        typography,
+        isFocused,
+        maxHeight,
+        radiuses,
+        borders,
+        spaces,
+        colors,
+        title,
+        type
+    });
+
+    useEffect(() => {
+        if(initialValue) {
+            inputRef.current?.setNativeProps({
+                text: initialValue
+            });
+        }
+    }, []);
+
+    useImperativeHandle(
+        ref,
+        () => ({
+            updateValue,
+            cleanText,
+            focus,
+            blur
+        }),
+        []
+    );
+
+    const titleProps: ITextProps = {
+        color: currentType.titleColor,
+        variant: "bodyLargeSize"
+    };
+
+    const iconProps: NCoreUIKit.IconCallbackProps = {
+        size: Number(typography.labelLargeSize.fontSize) + 6,
+        color: currentType.iconColor
+    };
+
+    if(isDisabled) {
+        iconProps.color = "disabled";
+    }
+
+    const blur = () => {
+        inputRef.current?.blur();
+    };
+
+    const focus = () => {
+        inputRef.current?.focus();
+    };
+
+    const cleanText = () => {
+        setValue("");
+
+        inputRef.current?.clear();
+
+        if(onChangeText) {
+            onChangeText("");
+        }
+    };
+
+    const updateValue = (text: string) => {
+        setValue(text);
+
+        inputRef.current?.setNativeProps({
+            text: text
+        });
+    };
+
+    const onFocus = () => {
+        setIsFocused(true);
+
+        if(onFocusProp) onFocusProp();
+    };
+
+    const onBlur = () => {
+        setIsFocused(false);
+
+        inputRef.current?.blur();
+
+        if(isAutoKeyboardDismissOnBlur) {
+            Keyboard.dismiss();
+        }
+
+        if(onBlurProp) onBlurProp();
+    };
+
+    const renderCleanButton = () => {
+        if(isDisabled) {
+            return null;
+        }
+
+        if(!isCleanEnabled || !value.length) {
+            return null;
+        }
+
+        return <TouchableOpacity
+            style={[
+                cleanIconStyle,
+                stylesheet.cleanButton,
+                cleanButtonDynamicStyle
+            ]}
+            onPress={() => {
+                if(inputRef.current) inputRef.current?.clear();
+
+                if(onChangeText) {
+                    onChangeText("");
+                }
+
+                setValue("");
+            }}
+        >
+            <CircleXIcon
+                color={colors.content.icon[currentType.iconColor]}
+                size={20}
+            />
+        </TouchableOpacity>;
+    };
+
+    const renderIcon = () => {
+        if (!IconComponentProp) {
+            return null;
+        }
+
+        return <TouchableOpacity
+            onPress={iconOnPress}
+            style={[
+                iconStyle,
+                stylesheet.icon,
+                iconDynamicStyle
+            ]}
+        >
+            <IconComponentProp
+                color={iconProps.color}
+                size={iconProps.size}
+            />
+        </TouchableOpacity>;
+    };
+
+    const renderRightIcon = () => {
+        if (!RightIconComponentProp) {
+            return null;
+        }
+
+        if(isCleanEnabled && value.length > 0) {
+            return null;
+        }
+
+        return <TouchableOpacity
+            onPress={rightIconOnPress}
+            style={[
+                rightIconStyle,
+                stylesheet.rightIcon,
+                rightIconDynamicStyle
+            ]}
+        >
+            <RightIconComponentProp
+                color={iconProps.color}
+                size={iconProps.size}
+            />
+        </TouchableOpacity>;
+    };
+
+    const renderHintIcon = () => {
+        if(!isShowHintTextIcon) {
+            return null;
+        }
+
+        if(HintTextIconProp) {
+            return <HintTextIconProp
+                color={isDisabled ? "disabled" : currentType.hintTextIconColor}
+                size={20}
+                style={[
+                    stylesheet.hintTextIcon,
+                    hintTextIconDynamicStyle
+                ]}
+            />;
+        }
+
+        const CurrentHintIcon = TextInputTypeIcon[type === "default" ? "question" : type];
+
+        let hintIconColor = colors.content.icon[currentType.hintTextIconColor];
+
+        if(isDisabled) {
+            hintIconColor = colors.system.state.content.disabled[styleType];
+        }
+
+        return <CurrentHintIcon
+            color={hintIconColor}
+            size={20}
+            style={[
+                stylesheet.hintTextIcon,
+                hintTextIconDynamicStyle
+            ]}
+        />;
+    };
+
+    const renderHintText = () => {
+        if (!hintText) {
+            return null;
+        }
+
+        return <View
+            style={[
+                hintTextContainerStyle,
+                stylesheet.hintText,
+                hintTextDynamicStyle
+            ]}
+        >
+            {renderHintIcon()}
+            <Text
+                customColor={isDisabled ? colors.system.state.content.disabled[styleType] : undefined}
+                color={currentType.hintTextColor}
+                variant="labelSmallSize"
+            >
+                {hintText}
+            </Text>
+        </View>;
+    };
+
+    const renderRequired = () => {
+        if(!isRequired) {
+            return null;
+        }
+
+        return <Text
+            color="danger"
+            style={[
+                stylesheet.required,
+                requiredDynamicStyle
+            ]}
+        >*</Text>;
+    };
+
+    const renderSubtitle = () => {
+        if(!isShowSubTitle && !isOptional) {
+            return null;
+        }
+
+        return <Text
+            variant="labelLargeSize"
+            color={titleProps.color}
+            style={[
+                stylesheet.subTitle,
+                subTitleDynamicStyle
+            ]}
+        >
+            ( {isOptional ? localize("is-optional") : subTitle} )
+        </Text>;
+    };
+
+    const renderTitle = () => {
+        if (!title) {
+            return null;
+        }
+
+        return <View
+            style={[
+                stylesheet.titleContainer,
+                titleContainerDynamicStyle
+            ]}
+        >
+            {renderRequired()}
+            <Text
+                {...titleProps}
+                variant={titleProps.variant}
+                color={titleProps.color}
+                style={[
+                    stylesheet.title,
+                    titleDynamicStyle
+                ]}
+            >
+                {title}
+            </Text>
+            {renderSubtitle()}
+        </View>;
+    };
+
+    const renderLengthLimiter = () => {
+        if(!isShowLengthLimiter || !maxLength) {
+            return null;
+        }
+
+        return <View
+            style={[
+                stylesheet.lengthLimiterContainer,
+                lengthLimiterContainerDynamicStyle
+            ]}
+        >
+            <Text>
+                {value.length} / {maxLength}
+            </Text>
+        </View>;
+    };
+
+    const renderInput = () => {
+        return <View
+            style={[
+                stylesheet.inputContainer,
+                inputContainerDynamicStyle
+            ]}
+        >
+            <NativeTextInput
+                {...props}
+                placeholderTextColor={colors.content.text[currentType.placeholderColor]}
+                underlineColorAndroid="rgba(255,255,255,0)"
+                placeholder={placeholder}
+                allowFontScaling={false}
+                editable={!isDisabled}
+                maxLength={maxLength}
+                multiline={true}
+                onFocus={onFocus}
+                onBlur={onBlur}
+                ref={inputRef}
+                onEndEditing={(t) => {
+                    const text = t.nativeEvent.text;
+
+                    if(!isUpdateOnRealtime) {
+                        if (validation) {
+                            if (validation(text)) {
+                                setValue(text);
+
+                                if(onChangeText) onChangeText(text);
+                            }
+                        } else {
+                            setValue(text);
+
+                            if(onChangeText) onChangeText(text);
+                        }
+                    }
+                }}
+                onChangeText={(text) => {
+                    if(isUpdateOnRealtime) {
+                        if (validation) {
+                            if (validation(text)) {
+                                setValue(text);
+
+                                if(onChangeText) onChangeText(text);
+                            }
+                        } else {
+                            setValue(text);
+
+                            if(onChangeText) onChangeText(text);
+                        }
+                    }
+                }}
+                style={[
+                    inputStyle,
+                    stylesheet.input,
+                    inputDynamicStyle
+                ]}
+            />
+            {renderLengthLimiter()}
+        </View>;
+    };
+
+    const renderOverlay = () => {
+        return <View
+            style={[
+                stylesheet.overlay,
+                overlayDynamicStyle
+            ]}
+        />;
+    };
+
+    return <TouchableOpacity
+        disabled={isDisabled}
+        style={[
+            style,
+            stylesheet.container,
+            containerDynamicStyle
+        ]}
+        onPress={() => {
+            if(!isDisabled) inputRef.current?.focus();
+        }}
+    >
+        {renderTitle()}
+
+        <View
+            style={[
+                contentContainerStyle,
+                stylesheet.content,
+                contentDynamicStyle
+            ]}
+        >
+            {renderOverlay()}
+
+            {renderIcon()}
+
+            {renderInput()}
+
+            {renderCleanButton()}
+            {renderRightIcon()}
+        </View>
+
+        {renderHintText()}
+    </TouchableOpacity>;
+};
+export default forwardRef(TextAreaInput);

+ 294 - 0
src/components/textAreaInput/stylesheet.ts

@@ -0,0 +1,294 @@
+import {
+    type ViewStyle,
+    type TextStyle,
+    StyleSheet
+} from "react-native";
+import {
+    type TextAreaInputDynamicStyleType,
+    type TextAreaInputTypes,
+    type TextAreaInputType
+} from "./type";
+import type {
+    Mutable
+} from "../../types";
+
+export const TEXT_AREA_INPUT_TYPE_STYLES: Record<
+    TextAreaInputType,
+    TextAreaInputTypes
+> = {
+    default: {
+        focusBorderColor: "emphasized",
+        borderColor: "emphasized",
+        hintTextIconColor: "mid",
+        placeholderColor: "low",
+        containerColor: "mid",
+        hintTextColor: "mid",
+        titleColor: "high",
+        inputColor: "mid",
+        iconColor: "mid"
+    },
+    danger: {
+        placeholderColor: "dangerLow",
+        hintTextIconColor: "danger",
+        focusBorderColor: "danger",
+        containerColor: "danger",
+        hintTextColor: "danger",
+        borderColor: "danger",
+        titleColor: "danger",
+        inputColor: "danger",
+        iconColor: "danger"
+    },
+    success: {
+        placeholderColor: "successLow",
+        hintTextIconColor: "success",
+        focusBorderColor: "success",
+        containerColor: "success",
+        hintTextColor: "success",
+        borderColor: "success",
+        titleColor: "success",
+        inputColor: "success",
+        iconColor: "success"
+    },
+    warning: {
+        placeholderColor: "warningLow",
+        hintTextIconColor: "warning",
+        focusBorderColor: "warning",
+        containerColor: "warning",
+        hintTextColor: "warning",
+        borderColor: "warning",
+        titleColor: "warning",
+        inputColor: "warning",
+        iconColor: "warning"
+    },
+    info: {
+        placeholderColor: "infoLow",
+        hintTextIconColor: "info",
+        focusBorderColor: "info",
+        containerColor: "info",
+        hintTextColor: "info",
+        borderColor: "info",
+        titleColor: "info",
+        inputColor: "info",
+        iconColor: "info"
+    },
+    question: {
+        focusBorderColor: "emphasized",
+        borderColor: "emphasized",
+        hintTextIconColor: "mid",
+        placeholderColor: "low",
+        containerColor: "mid",
+        hintTextColor: "mid",
+        titleColor: "mid",
+        inputColor: "mid",
+        iconColor: "mid"
+    }
+};
+
+export const getTextAreaInputType = ({
+    type
+}: {
+    type: TextAreaInputType;
+}) => {
+    const currentType = TEXT_AREA_INPUT_TYPE_STYLES[type];
+
+    return currentType;
+};
+
+const stylesheet = StyleSheet.create({
+    container: {
+        flexDirection: "column",
+        boxSizing: "border-box",
+        display: "flex"
+    },
+    content: {
+        alignItems: "flex-start",
+        boxSizing: "border-box",
+        flexDirection: "row",
+        borderStyle: "solid",
+        position: "relative",
+        display: "flex",
+        minWidth: 250
+    },
+    input: {
+        backgroundColor: "transparent",
+        borderColor: "transparent",
+        textAlignVertical: "top",
+        paddingBottom: 0,
+        paddingRight: 0,
+        paddingLeft: 0,
+        borderWidth: 0,
+        paddingTop: 0,
+        minHeight: 55,
+        zIndex: 99
+    },
+    cleanButton: {
+        justifyContent: "center",
+        alignSelf: "flex-start",
+        alignItems: "center",
+        display: "flex",
+        zIndex: 99
+    },
+    hideTextIconContainer: {
+        justifyContent: "center",
+        alignItems: "center",
+        alignSelf: "center",
+        display: "flex",
+        zIndex: 99,
+        height: 18
+    },
+    titleContainer: {
+        flexDirection: "row",
+        alignItems: "center"
+    },
+    title: {
+    },
+    icon: {
+        justifyContent: "center",
+        alignContent: "center",
+        alignItems: "center",
+        display: "flex",
+        zIndex: 99
+    },
+    required: {
+    },
+    hintTextIcon: {
+    },
+    hintText: {
+        flexDirection: "row",
+        alignItems: "center",
+        display: "flex"
+    },
+    subTitle: {
+    },
+    overlay: {
+        position: "absolute",
+        zIndex: 98,
+        bottom: 0,
+        right: 0,
+        left: 0,
+        top: 0
+    },
+    rightIcon: {
+        justifyContent: "center",
+        alignItems: "center",
+        alignSelf: "center",
+        display: "flex",
+        zIndex: 99
+    },
+    lengthLimiterContainer: {
+        justifyContent: "flex-end",
+        flexDirection: "row"
+    },
+    inputContainer: {
+        flexDirection: "column",
+        flex: 1
+    }
+});
+
+export const useStyles = ({
+    spreadBehaviour,
+    inlineSpaces,
+    currentType,
+    typography,
+    isDisabled,
+    isFocused,
+    maxHeight,
+    radiuses,
+    borders,
+    colors,
+    spaces,
+    type
+}: TextAreaInputDynamicStyleType) => {
+    const styleType = type === "danger" ? "error" : type === "question" ? "neutral" : type;
+
+    const styles = {
+        container: {
+        } as Mutable<ViewStyle>,
+        content: {
+            backgroundColor: colors.content.container[currentType.containerColor],
+            borderColor: colors.content.container[currentType.containerColor],
+            paddingBottom: spaces.spacingMd,
+            paddingRight: spaces.spacingMd,
+            borderRadius: radiuses.actions,
+            paddingLeft: spaces.spacingMd,
+            paddingTop: spaces.spacingMd,
+            borderWidth: borders.line
+        } as Mutable<ViewStyle>,
+        input: {
+            ...typography.labelLargeSize,
+            color: colors.content.text[currentType.inputColor],
+            maxHeight: maxHeight
+        } as Mutable<TextStyle>,
+        cleanButton: {
+            marginLeft: spaces.spacingSm
+        } as Mutable<ViewStyle>,
+        hintTextIconContainer: {
+            marginLeft: spaces.spacingSm
+        } as Mutable<ViewStyle>,
+        titleContainer: {
+            marginBottom: spaces.spacingSm
+        } as Mutable<ViewStyle>,
+        title: {
+
+        } as Mutable<TextStyle>,
+        icon: {
+            marginRight: spaces.spacingSm
+        } as Mutable<ViewStyle>,
+        required: {
+            marginRight: inlineSpaces.required
+        } as Mutable<ViewStyle>,
+        hintTextIcon: {
+            marginRight: spaces.spacingXs
+        } as Mutable<ViewStyle>,
+        hintText: {
+            marginTop: spaces.spacingSm
+        } as Mutable<TextStyle>,
+        subTitle: {
+            marginLeft: inlineSpaces.subTitle
+        } as Mutable<TextStyle>,
+        overlay: {
+            borderRadius: radiuses.actions - 1
+        } as Mutable<ViewStyle>,
+        rightIcon: {
+            marginLeft: spaces.spacingSm
+        } as Mutable<ViewStyle>,
+        lengthLimiterContainer: {
+
+        } as Mutable<ViewStyle>,
+        inputContainer: {
+
+        } as Mutable<ViewStyle>
+    };
+
+    if(isDisabled) {
+        const disableStyleType = styleType === "default" ? "neutral" : styleType;
+
+        styles.overlay.backgroundColor = colors.system.state.overlay.disabled[disableStyleType];
+        styles.container.borderColor = colors.system.state.overlay.disabled[disableStyleType];
+
+        styles.input.color = colors.content.text.disabled;
+    }
+
+    if (spreadBehaviour === "baseline") {
+        styles.container.alignSelf = spreadBehaviour;
+        styles.container.width = "auto";
+    }
+
+    if (spreadBehaviour === "stretch") {
+        styles.container.alignSelf = spreadBehaviour;
+        styles.container.justifyContent = "center";
+        styles.container.flexShrink = 1;
+        styles.container.width = "100%";
+    }
+
+    if(isFocused && !isDisabled) {
+        if(type === "question" || type === "default") {
+            styles.content.borderColor = colors.content.border.emphasized;
+        } else {
+            styles.content.borderColor = colors.content.border[type];
+        }
+    }
+
+    return styles;
+};
+export default stylesheet;

+ 104 - 0
src/components/textAreaInput/type.ts

@@ -0,0 +1,104 @@
+import type {
+    ComponentRef
+} from "react";
+import {
+    type TextInputProps,
+    type StyleProp,
+    type ViewStyle,
+    type TextStyle,
+    TextInput
+} from "react-native";
+import {
+    type NCoreUIKitIcon
+} from "../../types";
+
+export type ITextAreaInputRef = {
+    updateValue: (text: string) => void;
+    cleanText: () => void;
+    focus: () => void;
+    blur: () => void;
+};
+
+export type TextAreaInputDynamicStyleType = {
+    inlineSpaces: NCoreUIKit.ActivePalette["inlineSpaces"];
+    typography: NCoreUIKit.ActivePalette["typography"];
+    spreadBehaviour?: TextAreaInputSpreadBehaviour;
+    radiuses: NCoreUIKit.ActivePalette["radiuses"];
+    spaces: NCoreUIKit.ActivePalette["spaces"];
+    colors: NCoreUIKit.ActivePalette["colors"];
+    currentType: TextAreaInputTypes;
+    borders: NCoreUIKit.Borders;
+    type: TextAreaInputType;
+    isDisabled?: boolean;
+    maxHeight?: number;
+    isFocused: boolean;
+    title?: string;
+    icon?: boolean;
+};
+
+export type TextAreaInputTypes = {
+    containerColor: keyof NCoreUIKit.ContainerContentColors;
+    focusBorderColor: keyof NCoreUIKit.BorderContentColors;
+    hintTextIconColor: keyof NCoreUIKit.IconContentColors;
+    placeholderColor: keyof NCoreUIKit.TextContentColors;
+    hintTextColor: keyof NCoreUIKit.TextContentColors;
+    borderColor: keyof NCoreUIKit.BorderContentColors;
+    inputColor: keyof NCoreUIKit.TextContentColors;
+    titleColor: keyof NCoreUIKit.TextContentColors;
+    iconColor: keyof NCoreUIKit.IconContentColors;
+};
+
+export type TextAreaInputInstance = NonNullable<ComponentRef<typeof TextInput>>;
+
+export type TextAreaInputType = "default" | "danger" | "warning" | "question" | "success" | "info";
+
+export type TextAreaInputSpreadBehaviour = "baseline" | "stretch" | "free";
+
+interface ITextAreaInputProps extends TextInputProps {
+    customTheme?: {
+        gapPropagation?: NCoreUIKit.GapPropagationKey;
+        sharpness?: NCoreUIKit.SharpnessKey;
+        paletteKey?: NCoreUIKit.PaletteKey;
+        themeKey?: NCoreUIKit.ThemeKey;
+    };
+    customLocalize?: {
+        activeLocale?: NCoreUIKit.LocaleKey;
+    };
+    spreadBehaviour?: TextAreaInputSpreadBehaviour;
+    onChangeText?: (value: string) => void;
+    validation?: (text: string) => boolean;
+    isAutoKeyboardDismissOnBlur?: boolean;
+    hintTextContainerStyle?: ViewStyle;
+    contentContainerStyle?: ViewStyle;
+    inputStyle?: StyleProp<TextStyle>;
+    isShowLengthLimiter?: boolean;
+    rightIconOnPress?: () => void;
+    hintTextIcon?: NCoreUIKitIcon;
+    isShowHintTextIcon?: boolean;
+    isUpdateOnRealtime?: boolean;
+    cleanIconStyle?: ViewStyle;
+    rightIconStyle?: ViewStyle;
+    rightIcon?: NCoreUIKitIcon;
+    isShowSubTitle?: boolean;
+    isCleanEnabled?: boolean;
+    iconOnPress?: () => void;
+    type?: TextAreaInputType;
+    initialValue?: string;
+    iconStyle?: ViewStyle;
+    icon?: NCoreUIKitIcon;
+    placeholder?: string;
+    isRequired?: boolean;
+    isDisabled?: boolean;
+    isOptional?: boolean;
+    onFocus?: () => void;
+    onBlur?: () => void;
+    maxHeight?: number;
+    hintText?: string;
+    subTitle?: string;
+    style?: ViewStyle;
+    title?: string;
+    id?: string;
+};
+export type {
+    ITextAreaInputProps as default
+};

+ 74 - 43
src/components/textInput/index.tsx

@@ -7,6 +7,7 @@ import {
 import {
     TextInput as NativeTextInput,
     TouchableOpacity,
+    Keyboard,
     View
 } from "react-native";
 import type ITextInputProps from "./type";
@@ -24,32 +25,32 @@ import {
     NCoreUIKitTheme
 } from "../../core/hooks";
 import {
-    type RefForwardingComponent,
-    type INCoreUIKitIconProps,
-    type NCoreUIKitIcon
+    type RefForwardingComponent
 } from "../../types";
 import type ITextProps from "../text/type";
 import {
-    BadgeQuestionMarkIcon,
-    BadgeSuccessIcon,
-    BadgeDangerIcon,
-    BadgeAlertIcon,
-    BadgeInfoIcon,
-    EyeOpenedIcon,
-    EyeClosedIcon,
-    CleanIcon
-} from "../../assets/svg";
+    BadgeQuestionMark as BadgeQuestionMarkIcon,
+    BadgeAlert as BadgeAlertIcon,
+    BadgeCheck as BadgeCheckIcon,
+    BadgeInfo as BadgeInfoIcon,
+    EyeClosed as EyeClosedIcon,
+    CircleX as CircleXIcon,
+    BadgeX as BadgeXIcon,
+    type LucideIcon,
+    Eye as EyeIcon
+} from "lucide-react-native";
 import Text from "../text";
 
-const TextInputTypeIcon: Record<Exclude<TextInputType, "default">, NCoreUIKitIcon> = {
+const TextInputTypeIcon: Record<Exclude<TextInputType, "default">, LucideIcon> = {
     "question": BadgeQuestionMarkIcon,
-    "success": BadgeSuccessIcon,
+    "success": BadgeCheckIcon,
     "warning": BadgeAlertIcon,
-    "danger": BadgeDangerIcon,
-    "info": BadgeInfoIcon
+    "info": BadgeInfoIcon,
+    "danger": BadgeXIcon
 };
 
 const TextInput: RefForwardingComponent<ITextInputRef, ITextInputProps> = ({
+    isAutoKeyboardDismissOnBlur = true,
     rightIcon: RightIconComponentProp,
     hintTextIcon: HintTextIconProp,
     spreadBehaviour = "baseline",
@@ -103,6 +104,25 @@ const TextInput: RefForwardingComponent<ITextInputRef, ITextInputProps> = ({
         type
     });
 
+    const inputRef = useRef<TextInputInstance | null>(null);
+
+    const styleType = type === "default" ? "neutral" : type === "question" ? "neutral" : type === "danger" ? "error" : type;
+
+    const [
+        value,
+        setValue
+    ] = useState(initialValue ? initialValue : "");
+
+    const [
+        hideValue,
+        setHideValue
+    ] = useState(true);
+
+    const [
+        isFocused,
+        setIsFocused
+    ] = useState(false);
+
     const {
         hideTextIconContainer: hideTextIconContainerDynamicStyle,
         titleContainer: titleContainerDynamicStyle,
@@ -125,6 +145,7 @@ const TextInput: RefForwardingComponent<ITextInputRef, ITextInputProps> = ({
         currentType,
         isDisabled,
         typography,
+        isFocused,
         radiuses,
         borders,
         spaces,
@@ -133,20 +154,6 @@ const TextInput: RefForwardingComponent<ITextInputRef, ITextInputProps> = ({
         type
     });
 
-    const inputRef = useRef<TextInputInstance | null>(null);
-
-    const styleType = type === "default" ? "neutral" : type === "question" ? "neutral" : type === "danger" ? "error" : type;
-
-    const [
-        value,
-        setValue
-    ] = useState(initialValue ? initialValue : "");
-
-    const [
-        hideValue,
-        setHideValue
-    ] = useState(true);
-
     useImperativeHandle(
         ref,
         () => ({
@@ -163,7 +170,7 @@ const TextInput: RefForwardingComponent<ITextInputRef, ITextInputProps> = ({
         variant: "bodyLargeSize"
     };
 
-    const iconProps: INCoreUIKitIconProps = {
+    const iconProps: NCoreUIKit.IconCallbackProps = {
         size: Number(typography.labelLargeSize.fontSize) + 6,
         color: currentType.iconColor
     };
@@ -182,7 +189,9 @@ const TextInput: RefForwardingComponent<ITextInputRef, ITextInputProps> = ({
 
     const cleanText = () => {
         setValue("");
+
         inputRef.current?.clear();
+
         if(onChangeText) {
             onChangeText("");
         }
@@ -190,16 +199,27 @@ const TextInput: RefForwardingComponent<ITextInputRef, ITextInputProps> = ({
 
     const updateValue = (text: string) => {
         setValue(text);
+
         inputRef.current?.setNativeProps({
             text: text
         });
     };
 
     const onFocus = () => {
+        setIsFocused(true);
+
         if(onFocusProp) onFocusProp();
     };
 
     const onBlur = () => {
+        setIsFocused(false);
+
+        inputRef.current?.blur();
+
+        if(isAutoKeyboardDismissOnBlur) {
+            Keyboard.dismiss();
+        }
+
         if(onBlurProp) onBlurProp();
     };
 
@@ -227,14 +247,17 @@ const TextInput: RefForwardingComponent<ITextInputRef, ITextInputProps> = ({
                 cleanButtonDynamicStyle
             ]}
             onPress={() => {
+                if(inputRef.current) inputRef.current.clear();
+
                 if(onChangeText) {
                     onChangeText("");
                 }
+
                 setValue("");
             }}
         >
-            <CleanIcon
-                color="mid"
+            <CircleXIcon
+                color={colors.content.icon[currentType.iconColor]}
                 size={20}
             />
         </TouchableOpacity>;
@@ -306,12 +329,12 @@ const TextInput: RefForwardingComponent<ITextInputRef, ITextInputProps> = ({
             ]}
         >
             {hideValue ?
-                <EyeOpenedIcon
-                    color={iconProps.color}
+                <EyeIcon
+                    color={colors.content.icon[iconProps.color]}
                     size={20}
                 /> :
                 <EyeClosedIcon
-                    color={iconProps.color}
+                    color={colors.content.icon[iconProps.color]}
                     size={20}
                 />
             }
@@ -325,7 +348,7 @@ const TextInput: RefForwardingComponent<ITextInputRef, ITextInputProps> = ({
 
         if(HintTextIconProp) {
             return <HintTextIconProp
-                color={isDisabled ? "disabled" : currentType.hideTextIconColor}
+                color={isDisabled ? "disabled" : currentType.hintTextIconColor}
                 size={20}
                 style={[
                     stylesheet.hintTextIcon,
@@ -336,9 +359,14 @@ const TextInput: RefForwardingComponent<ITextInputRef, ITextInputProps> = ({
 
         const CurrentHintIcon = TextInputTypeIcon[type === "default" ? "question" : type];
 
+        let hintIconColor = colors.content.icon[currentType.hintTextIconColor];
+
+        if(isDisabled) {
+            hintIconColor = colors.system.state.content.disabled[styleType];
+        }
+
         return <CurrentHintIcon
-            customColor={isDisabled ? colors.system.state.content.disabled[styleType] : undefined}
-            color={currentType.hideTextIconColor}
+            color={hintIconColor}
             size={20}
             style={[
                 stylesheet.hintTextIcon,
@@ -362,7 +390,7 @@ const TextInput: RefForwardingComponent<ITextInputRef, ITextInputProps> = ({
             {renderHintIcon()}
             <Text
                 customColor={isDisabled ? colors.system.state.content.disabled[styleType] : undefined}
-                color={currentType.hideTextColor}
+                color={currentType.hintTextColor}
                 variant="labelSmallSize"
             >
                 {hintText}
@@ -441,23 +469,26 @@ const TextInput: RefForwardingComponent<ITextInputRef, ITextInputProps> = ({
             onFocus={onFocus}
             onBlur={onBlur}
             ref={inputRef}
-            value={value}
             onChangeText={(text) => {
                 const inputValue = text.replace(/\n/g, "");
 
                 if (inputValue === "") {
                     setValue("");
+
                     if(onChangeText) onChangeText("");
+
                     return;
                 }
 
                 if (validation) {
                     if (validation(inputValue)) {
                         setValue(inputValue);
+
                         if(onChangeText) onChangeText(inputValue);
                     }
                 } else {
                     setValue(inputValue);
+
                     if(onChangeText) onChangeText(inputValue);
                 }
             }}
@@ -498,8 +529,6 @@ const TextInput: RefForwardingComponent<ITextInputRef, ITextInputProps> = ({
                 contentDynamicStyle
             ]}
         >
-            {renderOverlay()}
-
             {renderIcon()}
 
             {renderInput()}
@@ -507,6 +536,8 @@ const TextInput: RefForwardingComponent<ITextInputRef, ITextInputProps> = ({
             {renderCleanButton()}
             {renderHideTextIcon()}
             {renderRightIcon()}
+
+            {renderOverlay()}
         </View>
 
         {renderHintText()}

+ 22 - 13
src/components/textInput/stylesheet.ts

@@ -19,20 +19,20 @@ export const TEXT_INPUT_TYPE_STYLES: Record<
     default: {
         focusBorderColor: "emphasized",
         borderColor: "emphasized",
-        hideTextIconColor: "mid",
+        hintTextIconColor: "mid",
         placeholderColor: "low",
         containerColor: "mid",
-        hideTextColor: "mid",
+        hintTextColor: "mid",
         titleColor: "high",
         inputColor: "mid",
         iconColor: "mid"
     },
     danger: {
         placeholderColor: "dangerLow",
-        hideTextIconColor: "danger",
+        hintTextIconColor: "danger",
         focusBorderColor: "danger",
         containerColor: "danger",
-        hideTextColor: "danger",
+        hintTextColor: "danger",
         borderColor: "danger",
         titleColor: "danger",
         inputColor: "danger",
@@ -40,10 +40,10 @@ export const TEXT_INPUT_TYPE_STYLES: Record<
     },
     success: {
         placeholderColor: "successLow",
-        hideTextIconColor: "success",
+        hintTextIconColor: "success",
         focusBorderColor: "success",
         containerColor: "success",
-        hideTextColor: "success",
+        hintTextColor: "success",
         borderColor: "success",
         titleColor: "success",
         inputColor: "success",
@@ -51,10 +51,10 @@ export const TEXT_INPUT_TYPE_STYLES: Record<
     },
     warning: {
         placeholderColor: "warningLow",
-        hideTextIconColor: "warning",
+        hintTextIconColor: "warning",
         focusBorderColor: "warning",
         containerColor: "warning",
-        hideTextColor: "warning",
+        hintTextColor: "warning",
         borderColor: "warning",
         titleColor: "warning",
         inputColor: "warning",
@@ -62,10 +62,10 @@ export const TEXT_INPUT_TYPE_STYLES: Record<
     },
     info: {
         placeholderColor: "infoLow",
-        hideTextIconColor: "info",
+        hintTextIconColor: "info",
         focusBorderColor: "info",
         containerColor: "info",
-        hideTextColor: "info",
+        hintTextColor: "info",
         borderColor: "info",
         titleColor: "info",
         inputColor: "info",
@@ -74,10 +74,10 @@ export const TEXT_INPUT_TYPE_STYLES: Record<
     question: {
         focusBorderColor: "emphasized",
         borderColor: "emphasized",
-        hideTextIconColor: "mid",
+        hintTextIconColor: "mid",
         placeholderColor: "low",
         containerColor: "mid",
-        hideTextColor: "mid",
+        hintTextColor: "mid",
         titleColor: "mid",
         inputColor: "mid",
         iconColor: "mid"
@@ -93,7 +93,7 @@ export const getTextInputType = ({
 
     return currentType;
 };
-// TODO: PLACECHOLDER CODE ADD.
+
 const stylesheet = StyleSheet.create({
     container: {
         flexDirection: "column",
@@ -184,6 +184,7 @@ export const useStyles = ({
     currentType,
     typography,
     isDisabled,
+    isFocused,
     radiuses,
     borders,
     colors,
@@ -265,6 +266,14 @@ export const useStyles = ({
         styles.container.width = "100%";
     }
 
+    if(isFocused && !isDisabled) {
+        if(type === "question" || type === "default") {
+            styles.content.borderColor = colors.content.border.emphasized;
+        } else {
+            styles.content.borderColor = colors.content.border[type];
+        }
+    }
+
     return styles;
 };
 export default stylesheet;

+ 8 - 3
src/components/textInput/type.ts

@@ -1,3 +1,6 @@
+import type {
+    ComponentRef
+} from "react";
 import {
     type TextInputProps,
     type StyleProp,
@@ -27,6 +30,7 @@ export type TextInputDynamicStyleType = {
     borders: NCoreUIKit.Borders;
     isDisabled?: boolean;
     type: TextInputType;
+    isFocused: boolean;
     title?: string;
     icon?: boolean;
 };
@@ -34,16 +38,16 @@ export type TextInputDynamicStyleType = {
 export type TextInputTypes = {
     containerColor: keyof NCoreUIKit.ContainerContentColors;
     focusBorderColor: keyof NCoreUIKit.BorderContentColors;
-    hideTextIconColor: keyof NCoreUIKit.IconContentColors;
+    hintTextIconColor: keyof NCoreUIKit.IconContentColors;
     placeholderColor: keyof NCoreUIKit.TextContentColors;
-    hideTextColor: keyof NCoreUIKit.TextContentColors;
+    hintTextColor: keyof NCoreUIKit.TextContentColors;
     borderColor: keyof NCoreUIKit.BorderContentColors;
     inputColor: keyof NCoreUIKit.TextContentColors;
     titleColor: keyof NCoreUIKit.TextContentColors;
     iconColor: keyof NCoreUIKit.IconContentColors;
 };
 
-export type TextInputInstance = NonNullable<React.ComponentRef<typeof TextInput>>;
+export type TextInputInstance = NonNullable<ComponentRef<typeof TextInput>>;
 
 export type TextInputType = "default" | "danger" | "warning" | "question" | "success" | "info";
 
@@ -64,6 +68,7 @@ interface ITextInputProps extends TextInputProps {
     spreadBehaviour?: TextInputSpreadBehaviour;
     onChangeText?: (value: string) => void;
     validation?: (text: string) => boolean;
+    isAutoKeyboardDismissOnBlur?: boolean;
     hintTextContainerStyle?: ViewStyle;
     contentContainerStyle?: ViewStyle;
     inputStyle?: StyleProp<TextStyle>;

+ 2 - 0
src/index.tsx

@@ -15,10 +15,12 @@ export {
 
 export {
     PageContainer,
+    TextAreaInput,
     BottomSheet,
     SelectSheet,
     TextInput,
     SelectBox,
+    SnackBar,
     CheckBox,
     Loading,
     Dialog,

+ 6 - 1
src/types/icon.ts

@@ -12,4 +12,9 @@ export interface INCoreUIKitIconProps {
     size?: number;
 }
 
-export type NCoreUIKitIcon = FC<INCoreUIKitIconProps>;
+export type INCoreUIKitIconCallbackProps = Omit<INCoreUIKitIconProps, "color" | "size"> & {
+    color: keyof NCoreUIKit.IconContentColors;
+    size: number;
+};
+
+export type NCoreUIKitIcon = FC<INCoreUIKitIconCallbackProps>;

+ 6 - 0
src/types/index.ts

@@ -1,6 +1,9 @@
 import {
     type ForwardRefRenderFunction
 } from "react";
+import {
+    type INCoreUIKitIconCallbackProps
+} from "./icon";
 import {
     type LocalizeType,
     type LocaleType
@@ -24,6 +27,7 @@ export type {
 } from "./portalize";
 
 export type {
+    INCoreUIKitIconCallbackProps,
     INCoreUIKitIconProps,
     NCoreUIKitIcon
 } from "./icon";
@@ -71,6 +75,8 @@ declare global {
         type LocaleKey = LocaleType;
         type ThemeKey = ThemeType;
 
+        type IconCallbackProps = INCoreUIKitIconCallbackProps;
+
         interface ActivePalette {
             inlineSpaces: InlineSpaces;
             typography: Typography;