|
@@ -29,6 +29,9 @@ import {
|
|
|
type INCoreUIKitIconProps,
|
|
type INCoreUIKitIconProps,
|
|
|
type NCoreUIKitIcon
|
|
type NCoreUIKitIcon
|
|
|
} from "../../types";
|
|
} from "../../types";
|
|
|
|
|
+import type {
|
|
|
|
|
+ IBottomSheetRef
|
|
|
|
|
+} from "../bottomSheet/type";
|
|
|
import type ITextProps from "../text/type";
|
|
import type ITextProps from "../text/type";
|
|
|
import {
|
|
import {
|
|
|
CheckIcon
|
|
CheckIcon
|
|
@@ -46,8 +49,9 @@ import {
|
|
|
} from "../../utils";
|
|
} from "../../utils";
|
|
|
import BottomSheet from "../bottomSheet";
|
|
import BottomSheet from "../bottomSheet";
|
|
|
import TextInput from "../textInput";
|
|
import TextInput from "../textInput";
|
|
|
-import Text from "../text";
|
|
|
|
|
import Loading from "../loading";
|
|
import Loading from "../loading";
|
|
|
|
|
+import Button from "../button";
|
|
|
|
|
+import Text from "../text";
|
|
|
|
|
|
|
|
const SelectBoxTypeIcon: Record<Exclude<SelectBoxType, "default">, NCoreUIKitIcon> = {
|
|
const SelectBoxTypeIcon: Record<Exclude<SelectBoxType, "default">, NCoreUIKitIcon> = {
|
|
|
"question": BadgeQuestionMarkIcon,
|
|
"question": BadgeQuestionMarkIcon,
|
|
@@ -58,6 +62,7 @@ const SelectBoxTypeIcon: Record<Exclude<SelectBoxType, "default">, NCoreUIKitIco
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
function SelectBox<T>({
|
|
function SelectBox<T>({
|
|
|
|
|
+ renderLoadingIcon : LoadingIconComponentProp,
|
|
|
rightIcon: RightIconComponentProp,
|
|
rightIcon: RightIconComponentProp,
|
|
|
hintTextIcon: HintTextIconProp,
|
|
hintTextIcon: HintTextIconProp,
|
|
|
spreadBehaviour = "baseline",
|
|
spreadBehaviour = "baseline",
|
|
@@ -113,6 +118,8 @@ function SelectBox<T>({
|
|
|
localize
|
|
localize
|
|
|
} = NCoreUIKitLocalize.useContext();
|
|
} = NCoreUIKitLocalize.useContext();
|
|
|
|
|
|
|
|
|
|
+ const bottomSheetRef = useRef<IBottomSheetRef>(null);
|
|
|
|
|
+
|
|
|
const selectBoxKey = useRef(customKey ? customKey : uuid());
|
|
const selectBoxKey = useRef(customKey ? customKey : uuid());
|
|
|
|
|
|
|
|
const currentType = getSelectBoxType({
|
|
const currentType = getSelectBoxType({
|
|
@@ -120,7 +127,13 @@ function SelectBox<T>({
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const {
|
|
const {
|
|
|
|
|
+ bottomSheetContentContainer: bottomSheetContentContainerDynamicStyle,
|
|
|
bottomSheetHeaderContainer: bottomSheetHeaderContainerDynamicStyle,
|
|
bottomSheetHeaderContainer: bottomSheetHeaderContainerDynamicStyle,
|
|
|
|
|
+ bottomSheetBottomContainer: bottomSheetBottomContainerDynamicStyle,
|
|
|
|
|
+ bottomSheetCancelButton: bottomSheetCancelButtonDynamicStyle,
|
|
|
|
|
+ bottomSheetHeaderTitle: bottomSheetHeaderTitleDynamicStyle,
|
|
|
|
|
+ bottomSheetOkButton: bottomSheetOkButtonDynamicStyle,
|
|
|
|
|
+ checkIconContainer: checkIconContainerDynamicStyle,
|
|
|
loadingContainer: loadingContainerDynamicStyle,
|
|
loadingContainer: loadingContainerDynamicStyle,
|
|
|
contentContainer: contentContainerDynamicStyle,
|
|
contentContainer: contentContainerDynamicStyle,
|
|
|
titleContainer: titleContainerDynamicStyle,
|
|
titleContainer: titleContainerDynamicStyle,
|
|
@@ -141,6 +154,7 @@ function SelectBox<T>({
|
|
|
icon: IconComponentProp ? true : false,
|
|
icon: IconComponentProp ? true : false,
|
|
|
spreadBehaviour,
|
|
spreadBehaviour,
|
|
|
inlineSpaces,
|
|
inlineSpaces,
|
|
|
|
|
+ isSearchable,
|
|
|
currentType,
|
|
currentType,
|
|
|
isDisabled,
|
|
isDisabled,
|
|
|
radiuses,
|
|
radiuses,
|
|
@@ -176,7 +190,7 @@ function SelectBox<T>({
|
|
|
const [
|
|
const [
|
|
|
isLoading,
|
|
isLoading,
|
|
|
setIsLoading
|
|
setIsLoading
|
|
|
- ] = useState(true);
|
|
|
|
|
|
|
+ ] = useState(false);
|
|
|
|
|
|
|
|
const [
|
|
const [
|
|
|
isMoreLoading,
|
|
isMoreLoading,
|
|
@@ -201,8 +215,10 @@ function SelectBox<T>({
|
|
|
updateSelections,
|
|
updateSelections,
|
|
|
cleanSelections,
|
|
cleanSelections,
|
|
|
updateData,
|
|
updateData,
|
|
|
|
|
+ cancel,
|
|
|
focus,
|
|
focus,
|
|
|
- blur
|
|
|
|
|
|
|
+ blur,
|
|
|
|
|
+ ok
|
|
|
}),
|
|
}),
|
|
|
[]
|
|
[]
|
|
|
);
|
|
);
|
|
@@ -262,17 +278,43 @@ function SelectBox<T>({
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const blur = () => {
|
|
const blur = () => {
|
|
|
|
|
+ if(!isWorkWithRealtime) {
|
|
|
|
|
+ setTempSelectedItems([]);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
setIsActive(false);
|
|
setIsActive(false);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const focus = () => {
|
|
const focus = () => {
|
|
|
|
|
+ if(!isWorkWithRealtime) {
|
|
|
|
|
+ setTempSelectedItems(selectedItems);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
setIsActive(true);
|
|
setIsActive(true);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ const cancel = () => {
|
|
|
|
|
+ if(!isWorkWithRealtime) {
|
|
|
|
|
+ bottomSheetRef.current?.close(() => {
|
|
|
|
|
+ blur();
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const ok = () => {
|
|
|
|
|
+ if(!isWorkWithRealtime) {
|
|
|
|
|
+ setSelectedItems(tempSelectedItems);
|
|
|
|
|
+
|
|
|
|
|
+ bottomSheetRef.current?.close(() => {
|
|
|
|
|
+ blur();
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
const cleanSelections = () => {
|
|
const cleanSelections = () => {
|
|
|
- if(isWorkWithRealtime) {
|
|
|
|
|
- setSelectedItems([]);
|
|
|
|
|
- } else {
|
|
|
|
|
|
|
+ setSelectedItems([]);
|
|
|
|
|
+
|
|
|
|
|
+ if(!isWorkWithRealtime) {
|
|
|
setTempSelectedItems([]);
|
|
setTempSelectedItems([]);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -648,98 +690,153 @@ function SelectBox<T>({
|
|
|
loadingContainerDynamicStyle
|
|
loadingContainerDynamicStyle
|
|
|
]}
|
|
]}
|
|
|
>
|
|
>
|
|
|
- <Loading/>
|
|
|
|
|
|
|
+ {LoadingIconComponentProp ? <LoadingIconComponentProp/> : <Loading/>}
|
|
|
</View>;
|
|
</View>;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return data.map((item: T & SelectedItem | SelectedItem, index: number) => {
|
|
|
|
|
- const isSelected = mainSelectedItems.findIndex((sI: SelectedItem) => {
|
|
|
|
|
- return sI.__key === item.__key;
|
|
|
|
|
- }) !== -1;
|
|
|
|
|
-
|
|
|
|
|
- if(renderItem) {
|
|
|
|
|
- return renderItem({
|
|
|
|
|
- key: keyExtractor(item as T & SelectedItem, index),
|
|
|
|
|
- onSelect: (sItem) => {
|
|
|
|
|
- selectObject(sItem);
|
|
|
|
|
- },
|
|
|
|
|
- selectedItems: mainSelectedItems,
|
|
|
|
|
- setIsLoading,
|
|
|
|
|
- isSelected,
|
|
|
|
|
- searchText,
|
|
|
|
|
- index,
|
|
|
|
|
- item,
|
|
|
|
|
- data
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ return <View
|
|
|
|
|
+ style={[
|
|
|
|
|
+ bottomSheetContentContainerDynamicStyle
|
|
|
|
|
+ ]}
|
|
|
|
|
+ >
|
|
|
|
|
+ {
|
|
|
|
|
+ data.map((item: T & SelectedItem | SelectedItem, index: number) => {
|
|
|
|
|
+ const isSelected = mainSelectedItems.findIndex((sI: SelectedItem) => {
|
|
|
|
|
+ return sI.__key === item.__key;
|
|
|
|
|
+ }) !== -1;
|
|
|
|
|
+
|
|
|
|
|
+ if(renderItem) {
|
|
|
|
|
+ return renderItem({
|
|
|
|
|
+ key: keyExtractor(item as T & SelectedItem, index),
|
|
|
|
|
+ onSelect: (sItem) => {
|
|
|
|
|
+ selectObject(sItem);
|
|
|
|
|
+ },
|
|
|
|
|
+ selectedItems: mainSelectedItems,
|
|
|
|
|
+ setIsLoading,
|
|
|
|
|
+ isSelected,
|
|
|
|
|
+ searchText,
|
|
|
|
|
+ index,
|
|
|
|
|
+ item,
|
|
|
|
|
+ data
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return <TouchableOpacity
|
|
|
|
|
+ key={keyExtractor(item as T & SelectedItem, index)}
|
|
|
|
|
+ style={[
|
|
|
|
|
+ stylesheet.itemContainer,
|
|
|
|
|
+ itemContainerDynamicStyle
|
|
|
|
|
+ ]}
|
|
|
|
|
+ onPress={() => {
|
|
|
|
|
+ selectObject(item);
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={[
|
|
|
|
|
+ stylesheet.itemContentContainer
|
|
|
|
|
+ ]}
|
|
|
|
|
+ >
|
|
|
|
|
+ {renderOptionIcon ? renderOptionIcon({
|
|
|
|
|
+ item,
|
|
|
|
|
+ index
|
|
|
|
|
+ }) : null}
|
|
|
|
|
+ <Text
|
|
|
|
|
+ color={isSelected ? "emphasized" : undefined}
|
|
|
|
|
+ >{item.__title}</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={[
|
|
|
|
|
+ stylesheet.checkIconContainer,
|
|
|
|
|
+ checkIconContainerDynamicStyle
|
|
|
|
|
+ ]}
|
|
|
|
|
+ >
|
|
|
|
|
+ {isSelected ?
|
|
|
|
|
+ <CheckIcon
|
|
|
|
|
+ color={colors.content.icon.emphasized}
|
|
|
|
|
+ size={24}
|
|
|
|
|
+ /> : null}
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </TouchableOpacity>;
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
|
|
+ </View>;
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
- return <TouchableOpacity
|
|
|
|
|
- key={keyExtractor(item as T & SelectedItem, index)}
|
|
|
|
|
|
|
+ const renderBottomSheetHeader = () => {
|
|
|
|
|
+ return <View
|
|
|
|
|
+ style={[
|
|
|
|
|
+ stylesheet.bottomSheetHeaderContainer,
|
|
|
|
|
+ bottomSheetHeaderContainerDynamicStyle
|
|
|
|
|
+ ]}
|
|
|
|
|
+ >
|
|
|
|
|
+ <Text
|
|
|
|
|
+ variant="titleMediumSize"
|
|
|
style={[
|
|
style={[
|
|
|
- stylesheet.itemContainer,
|
|
|
|
|
- itemContainerDynamicStyle
|
|
|
|
|
|
|
+ bottomSheetHeaderTitleDynamicStyle
|
|
|
]}
|
|
]}
|
|
|
|
|
+ >
|
|
|
|
|
+ {title}
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ {isSearchable ? <TextInput
|
|
|
|
|
+ placeholder={localize("search")}
|
|
|
|
|
+ spreadBehaviour="stretch"
|
|
|
|
|
+ onChangeText={(text: string) => {
|
|
|
|
|
+ setSearchText(text);
|
|
|
|
|
+ }}
|
|
|
|
|
+ /> : null}
|
|
|
|
|
+ </View>;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const renderBottomSheetBottom = () => {
|
|
|
|
|
+ if(isWorkWithRealtime) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return <View
|
|
|
|
|
+ style={[
|
|
|
|
|
+ stylesheet.bottomSheetBottomContainer,
|
|
|
|
|
+ bottomSheetBottomContainerDynamicStyle
|
|
|
|
|
+ ]}
|
|
|
|
|
+ >
|
|
|
|
|
+ <Button
|
|
|
|
|
+ title={localize("cancel")}
|
|
|
|
|
+ spreadBehaviour="stretch"
|
|
|
|
|
+ variant="outline"
|
|
|
|
|
+ type="neutral"
|
|
|
onPress={() => {
|
|
onPress={() => {
|
|
|
- selectObject(item);
|
|
|
|
|
|
|
+ cancel();
|
|
|
}}
|
|
}}
|
|
|
- >
|
|
|
|
|
- <View
|
|
|
|
|
- style={[
|
|
|
|
|
- stylesheet.itemContentContainer
|
|
|
|
|
- ]}
|
|
|
|
|
- >
|
|
|
|
|
- {renderOptionIcon ? renderOptionIcon({
|
|
|
|
|
- item,
|
|
|
|
|
- index
|
|
|
|
|
- }) : null}
|
|
|
|
|
- <Text
|
|
|
|
|
- color={isSelected ? "onPrimary" : undefined}
|
|
|
|
|
- >{item.__title}</Text>
|
|
|
|
|
- </View>
|
|
|
|
|
- <View
|
|
|
|
|
- style={[
|
|
|
|
|
- {
|
|
|
|
|
- height: 24 + spaces.spacingSm,
|
|
|
|
|
- width: 24 + spaces.spacingSm
|
|
|
|
|
- }
|
|
|
|
|
- ]}
|
|
|
|
|
- >
|
|
|
|
|
- {isSelected ?
|
|
|
|
|
- <CheckIcon
|
|
|
|
|
- color={colors.content.icon.onPrimary}
|
|
|
|
|
- size={24}
|
|
|
|
|
- /> : null}
|
|
|
|
|
- </View>
|
|
|
|
|
- </TouchableOpacity>;
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ style={{
|
|
|
|
|
+ ...bottomSheetCancelButtonDynamicStyle
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ <Button
|
|
|
|
|
+ spreadBehaviour="stretch"
|
|
|
|
|
+ title={localize("ok")}
|
|
|
|
|
+ onPress={() => {
|
|
|
|
|
+ ok();
|
|
|
|
|
+ }}
|
|
|
|
|
+ style={{
|
|
|
|
|
+ ...bottomSheetOkButtonDynamicStyle
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </View>;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const renderBottomSheet = () => {
|
|
const renderBottomSheet = () => {
|
|
|
return <BottomSheet
|
|
return <BottomSheet
|
|
|
customKey={selectBoxKey.current}
|
|
customKey={selectBoxKey.current}
|
|
|
|
|
+ ref={bottomSheetRef}
|
|
|
|
|
+ isAutoHeight={true}
|
|
|
isActive={isActive}
|
|
isActive={isActive}
|
|
|
- onClose={() => {
|
|
|
|
|
- setIsActive(false);
|
|
|
|
|
|
|
+ renderBottom={() => {
|
|
|
|
|
+ return renderBottomSheetBottom();
|
|
|
}}
|
|
}}
|
|
|
renderHeader={() => {
|
|
renderHeader={() => {
|
|
|
- return <View
|
|
|
|
|
- style={[
|
|
|
|
|
- stylesheet.bottomSheetHeaderContainer,
|
|
|
|
|
- bottomSheetHeaderContainerDynamicStyle
|
|
|
|
|
- ]}
|
|
|
|
|
- >
|
|
|
|
|
- <Text
|
|
|
|
|
- variant="titleMediumSize"
|
|
|
|
|
- >
|
|
|
|
|
- {title}
|
|
|
|
|
- </Text>
|
|
|
|
|
- {isSearchable ? <TextInput
|
|
|
|
|
- spreadBehaviour="stretch"
|
|
|
|
|
- onChangeText={(text: string) => {
|
|
|
|
|
- setSearchText(text);
|
|
|
|
|
- }}
|
|
|
|
|
- /> : null}
|
|
|
|
|
- </View>;
|
|
|
|
|
|
|
+ return renderBottomSheetHeader();
|
|
|
|
|
+ }}
|
|
|
|
|
+ onClose={() => {
|
|
|
|
|
+ setIsActive(false);
|
|
|
}}
|
|
}}
|
|
|
>
|
|
>
|
|
|
{renderBottomSheetContent()}
|
|
{renderBottomSheetContent()}
|