Bladeren bron

Feature: BottomSheet integrated to SelectBox component.

lfabl 2 maanden geleden
bovenliggende
commit
8d5c3b4ed2

+ 1 - 0
example/package.json

@@ -17,6 +17,7 @@
         "expo": "~55.0.4",
         "expo-font": "~55.0.4",
         "expo-status-bar": "~55.0.4",
+        "lucide-react-native": "^1.8.0",
         "ncore-context": "^1.0.5",
         "react": "19.2.0",
         "react-dom": "19.2.0",

+ 14 - 3
src/components/bottomSheet/index.tsx

@@ -31,7 +31,8 @@ import type {
     IModalRef
 } from "../modal/type";
 import {
-    windowHeight
+    windowHeight,
+    uuid
 } from "../../utils";
 import Modal from "../modal";
 
@@ -59,13 +60,13 @@ const BottomSheet: RefForwardingComponent<IBottomSheetRef, IBottomSheetProps> =
     scrollViewStyle,
     modalProps,
     snapPoint,
+    customKey,
     children,
     onClosed,
     onOpened,
     onClose,
     onOpen,
     style,
-    key,
     ...props
 }, ref) => {
     const {
@@ -88,6 +89,8 @@ const BottomSheet: RefForwardingComponent<IBottomSheetRef, IBottomSheetProps> =
         setIsActive
     ] = useState(isActiveProp === undefined ? false : isActiveProp);
 
+    const bottomSheetKey = useRef(customKey ? customKey : uuid());
+
     let bottomSafeArea = isWrapSafeAreaContext ? bottom : 0;
     let topSafeArea = isWrapSafeAreaContext ? top : 0;
 
@@ -191,6 +194,12 @@ const BottomSheet: RefForwardingComponent<IBottomSheetRef, IBottomSheetProps> =
         isMeasured
     ]);
 
+    if(isActiveProp !== undefined) {
+        useEffect(() => {
+            setIsActive(isActiveProp);
+        }, [isActiveProp]);
+    }
+
     useEffect(() => {
         if (!isWorkAsFullScreen && !isCanFullScreenOnSwipe && snapPoint) {
             maxHeight.current = snapPoint;
@@ -588,6 +597,8 @@ const BottomSheet: RefForwardingComponent<IBottomSheetRef, IBottomSheetProps> =
                             }
                         }
 
+                        if(onClose) onClose();
+
                         Animated.timing(animatedTranslateY, {
                             useNativeDriver: false,
                             toValue: toValueT,
@@ -721,8 +732,8 @@ const BottomSheet: RefForwardingComponent<IBottomSheetRef, IBottomSheetProps> =
     return <Modal
         {...modalProps}
         isWorkWithPortal={isWorkWithPortal}
+        key={`${bottomSheetKey}-modal`}
         isContentRequired={false}
-        key={`${key}-modal`}
         isActive={isActive}
         alignContent="free"
         isAnimated={false}

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

@@ -42,8 +42,8 @@ interface IBottomSheetProps {
     onOpen?: () => void;
     snapPoint?: number;
     isActive?: boolean;
+    customKey?: string;
     style?: ViewStyle;
-    key: string;
 }
 export type {
     IBottomSheetProps as default

+ 63 - 6
src/components/selectBox/index.tsx

@@ -2,7 +2,10 @@ import {
     useImperativeHandle,
     forwardRef,
     useReducer,
-    type Ref
+    useEffect,
+    useState,
+    type Ref,
+    useRef
 } from "react";
 import {
     TouchableOpacity,
@@ -28,6 +31,9 @@ import {
     type NCoreUIKitIcon
 } from "../../types";
 import type ITextProps from "../text/type";
+import {
+    CheckIcon
+} from "lucide-react-native";
 import {
     BadgeQuestionMarkIcon,
     BadgeSuccessIcon,
@@ -36,6 +42,10 @@ import {
     BadgeInfoIcon,
     CleanIcon
 } from "../../assets/svg";
+import {
+    uuid
+} from "../../utils";
+import BottomSheet from "../bottomSheet";
 import Text from "../text";
 
 const SelectBoxTypeIcon: Record<Exclude<SelectBoxType, "default">, NCoreUIKitIcon> = {
@@ -66,6 +76,7 @@ function SelectBox<T>({
     variant = "text",
     type = "default",
     rightIconOnPress,
+    renderOptionIcon,
     rightIconStyle,
     isShowSubTitle,
     cleanIconStyle,
@@ -76,6 +87,7 @@ function SelectBox<T>({
     iconOnPress,
     isOptional,
     validation,
+    customKey,
     iconStyle,
     onChange,
     hintText,
@@ -95,6 +107,8 @@ function SelectBox<T>({
         localize
     } = NCoreUIKitLocalize.useContext();
 
+    const selectBoxKey = useRef(customKey ? customKey : uuid());
+
     const currentType = getSelectBoxType({
         type
     });
@@ -148,7 +162,7 @@ function SelectBox<T>({
     const [
         isActive,
         setIsActive
-    ] = useState(); --> continue
+    ] = useState(false);
 
     const [
         selectedItems,
@@ -169,6 +183,14 @@ function SelectBox<T>({
         []
     );
 
+    useEffect(() => {
+        if(isActive) {
+            if(onFocus) onFocus();
+        } else {
+            if(onBlur) onBlur();
+        }
+    }, [isActive]);
+
     const titleProps: ITextProps = {
         color: currentType.titleColor,
         variant: "bodyLargeSize"
@@ -184,11 +206,11 @@ function SelectBox<T>({
     }
 
     const blur = () => {
-        // inputRef.current?.blur();
+        setIsActive(false);
     };
 
     const focus = () => {
-        // inputRef.current?.focus();
+        setIsActive(true);
     };
 
     const cleanSelections = () => {
@@ -423,7 +445,7 @@ function SelectBox<T>({
             ]}
             onPress={() => {
                 if(!isDisabled) {
-
+                    focus();
                 }
             }}
         >
@@ -488,6 +510,40 @@ function SelectBox<T>({
         />;
     };
 
+    const renderBottomSheetContent = () => {
+        return data.map((item: T, index: number) => {
+            return <TouchableOpacity>
+                {renderOptionIcon ? renderOptionIcon({
+                    item,
+                    index
+                }) : null}
+                <Text></Text>
+                <View>
+                    <CheckIcon/>
+                </View>
+            </TouchableOpacity>;
+        });
+    };
+
+    const renderBottomSheet = () => {
+        return <BottomSheet
+            customKey={selectBoxKey.current}
+            isActive={isActive}
+            onClose={() => {
+                setIsActive(false);
+            }}
+            renderHeader={() => {
+                return <View>
+                    <Text>
+                        {title}
+                    </Text>
+                </View>;
+            }}
+        >
+            {renderBottomSheetContent()}
+        </BottomSheet>;
+    };
+
     return <View
         style={[
             style,
@@ -506,7 +562,7 @@ function SelectBox<T>({
             ]}
             onPress={() => {
                 if(!isDisabled) {
-
+                    focus();
                 }
             }}
         >
@@ -521,6 +577,7 @@ function SelectBox<T>({
         </TouchableOpacity>
 
         {renderHintText()}
+        {renderBottomSheet()}
     </View>;
 };
 export default forwardRef(SelectBox) as unknown as SelectBoxComponent;

+ 6 - 0
src/components/selectBox/type.ts

@@ -1,4 +1,5 @@
 import type {
+    ReactElement,
     ReactNode,
     Ref
 } from "react";
@@ -73,6 +74,10 @@ interface ISelectBoxProps<T> {
     rightIconOnPress?: () => void;
     hintTextIcon?: NCoreUIKitIcon;
     isShowHintTextIcon?: boolean;
+    renderOptionIcon?: (props: {
+        index: number;
+        item: T;
+    }) => ReactElement;
     cleanIconStyle?: ViewStyle;
     rightIconStyle?: ViewStyle;
     rightIcon?: NCoreUIKitIcon;
@@ -90,6 +95,7 @@ interface ISelectBoxProps<T> {
     onFocus?: () => void;
     type?: SelectBoxType;
     onBlur?: () => void;
+    customKey?: string;
     hintText?: string;
     subTitle?: string;
     style?: ViewStyle;

+ 12 - 0
yarn.lock

@@ -12015,6 +12015,17 @@ __metadata:
   languageName: node
   linkType: hard
 
+"lucide-react-native@npm:^1.8.0":
+  version: 1.8.0
+  resolution: "lucide-react-native@npm:1.8.0"
+  peerDependencies:
+    react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
+    react-native: "*"
+    react-native-svg: ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0
+  checksum: 10c0/3a04b9c2d8bf91c23a4c5ff64be4b27dbbc82df093e1a9c363d9ea7936e417a780a1226c84365ff2da32b90a9ecf73aaa1d7631421c66ba79299ffec6631f996
+  languageName: node
+  linkType: hard
+
 "macos-release@npm:^3.3.0":
   version: 3.4.0
   resolution: "macos-release@npm:3.4.0"
@@ -13169,6 +13180,7 @@ __metadata:
     expo: "npm:~55.0.4"
     expo-font: "npm:~55.0.4"
     expo-status-bar: "npm:~55.0.4"
+    lucide-react-native: "npm:^1.8.0"
     ncore-context: "npm:^1.0.5"
     react: "npm:19.2.0"
     react-dom: "npm:19.2.0"