|
@@ -33,9 +33,6 @@ import type {
|
|
|
IBottomSheetRef
|
|
IBottomSheetRef
|
|
|
} from "../bottomSheet/type";
|
|
} from "../bottomSheet/type";
|
|
|
import type ITextProps from "../text/type";
|
|
import type ITextProps from "../text/type";
|
|
|
-import {
|
|
|
|
|
- CheckIcon
|
|
|
|
|
-} from "lucide-react-native";
|
|
|
|
|
import {
|
|
import {
|
|
|
BadgeQuestionMarkIcon,
|
|
BadgeQuestionMarkIcon,
|
|
|
BadgeSuccessIcon,
|
|
BadgeSuccessIcon,
|
|
@@ -47,10 +44,7 @@ import {
|
|
|
import {
|
|
import {
|
|
|
uuid
|
|
uuid
|
|
|
} from "../../utils";
|
|
} from "../../utils";
|
|
|
-import BottomSheet from "../bottomSheet";
|
|
|
|
|
-import TextInput from "../textInput";
|
|
|
|
|
-import Loading from "../loading";
|
|
|
|
|
-import Button from "../button";
|
|
|
|
|
|
|
+import SelectSheet from "../selectSheet";
|
|
|
import Text from "../text";
|
|
import Text from "../text";
|
|
|
|
|
|
|
|
const SelectBoxTypeIcon: Record<Exclude<SelectBoxType, "default">, NCoreUIKitIcon> = {
|
|
const SelectBoxTypeIcon: Record<Exclude<SelectBoxType, "default">, NCoreUIKitIcon> = {
|
|
@@ -68,6 +62,7 @@ function SelectBox<T>({
|
|
|
spreadBehaviour = "baseline",
|
|
spreadBehaviour = "baseline",
|
|
|
isShowHintTextIcon = false,
|
|
isShowHintTextIcon = false,
|
|
|
isWorkWithRealtime = true,
|
|
isWorkWithRealtime = true,
|
|
|
|
|
+ isMultipleSelect = false,
|
|
|
icon: IconComponentProp,
|
|
icon: IconComponentProp,
|
|
|
hintTextContainerStyle,
|
|
hintTextContainerStyle,
|
|
|
removeSelectValidation,
|
|
removeSelectValidation,
|
|
@@ -98,6 +93,8 @@ function SelectBox<T>({
|
|
|
isOptional,
|
|
isOptional,
|
|
|
renderItem,
|
|
renderItem,
|
|
|
customKey,
|
|
customKey,
|
|
|
|
|
+ maxChoice,
|
|
|
|
|
+ minChoice,
|
|
|
iconStyle,
|
|
iconStyle,
|
|
|
onChange,
|
|
onChange,
|
|
|
hintText,
|
|
hintText,
|
|
@@ -127,17 +124,8 @@ function SelectBox<T>({
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const {
|
|
const {
|
|
|
- bottomSheetContentContainer: bottomSheetContentContainerDynamicStyle,
|
|
|
|
|
- bottomSheetHeaderContainer: bottomSheetHeaderContainerDynamicStyle,
|
|
|
|
|
- bottomSheetBottomContainer: bottomSheetBottomContainerDynamicStyle,
|
|
|
|
|
- bottomSheetCancelButton: bottomSheetCancelButtonDynamicStyle,
|
|
|
|
|
- bottomSheetHeaderTitle: bottomSheetHeaderTitleDynamicStyle,
|
|
|
|
|
- bottomSheetOkButton: bottomSheetOkButtonDynamicStyle,
|
|
|
|
|
- checkIconContainer: checkIconContainerDynamicStyle,
|
|
|
|
|
- loadingContainer: loadingContainerDynamicStyle,
|
|
|
|
|
contentContainer: contentContainerDynamicStyle,
|
|
contentContainer: contentContainerDynamicStyle,
|
|
|
titleContainer: titleContainerDynamicStyle,
|
|
titleContainer: titleContainerDynamicStyle,
|
|
|
- itemContainer: itemContainerDynamicStyle,
|
|
|
|
|
hintTextIcon: hintTextIconDynamicStyle,
|
|
hintTextIcon: hintTextIconDynamicStyle,
|
|
|
contentText: contentTextDynamicStyle,
|
|
contentText: contentTextDynamicStyle,
|
|
|
cleanButton: cleanButtonDynamicStyle,
|
|
cleanButton: cleanButtonDynamicStyle,
|
|
@@ -243,9 +231,9 @@ function SelectBox<T>({
|
|
|
|
|
|
|
|
setSearchedData(_searchedData);
|
|
setSearchedData(_searchedData);
|
|
|
} else {
|
|
} else {
|
|
|
- const _searchedData = prepareDatas(data.filter(dI => {
|
|
|
|
|
|
|
+ const _searchedData = data.filter(dI => {
|
|
|
return dI.__title.toLocaleLowerCase().includes(searchText.toLocaleLowerCase());
|
|
return dI.__title.toLocaleLowerCase().includes(searchText.toLocaleLowerCase());
|
|
|
- }) as Array<T & SelectedItem>, mainSelectedItems);
|
|
|
|
|
|
|
+ }) as Array<T & SelectedItem>;
|
|
|
|
|
|
|
|
setSearchedData(_searchedData);
|
|
setSearchedData(_searchedData);
|
|
|
}
|
|
}
|
|
@@ -400,26 +388,67 @@ function SelectBox<T>({
|
|
|
let _selectedItems = JSON.parse(JSON.stringify(mainSelectedItems));
|
|
let _selectedItems = JSON.parse(JSON.stringify(mainSelectedItems));
|
|
|
|
|
|
|
|
if(isAlreadySelected !== -1) {
|
|
if(isAlreadySelected !== -1) {
|
|
|
- if(removeSelectValidation) {
|
|
|
|
|
- if(removeSelectValidation(selectedItem)) {
|
|
|
|
|
- _selectedItems = _selectedItems.filter((sItem: SelectedItem) => sItem.__key !== selectedItem.__key);
|
|
|
|
|
|
|
+ let isProcessPerm = false;
|
|
|
|
|
+
|
|
|
|
|
+ if(isMultipleSelect) {
|
|
|
|
|
+ if(minChoice) {
|
|
|
|
|
+ if(_selectedItems.length > minChoice) {
|
|
|
|
|
+ isProcessPerm = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ isProcessPerm = true;
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
- _selectedItems = _selectedItems.filter((sItem: SelectedItem) => sItem.__key !== selectedItem.__key);
|
|
|
|
|
|
|
+ const _minChoice = minChoice === undefined ? 0 : minChoice;
|
|
|
|
|
+
|
|
|
|
|
+ if(_minChoice > 0) {
|
|
|
|
|
+ // TODO: make toast;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ isProcessPerm = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if(isProcessPerm) {
|
|
|
|
|
+ if(removeSelectValidation) {
|
|
|
|
|
+ if(removeSelectValidation(selectedItem)) {
|
|
|
|
|
+ _selectedItems = _selectedItems.filter((sItem: SelectedItem) => sItem.__key !== selectedItem.__key);
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ _selectedItems = _selectedItems.filter((sItem: SelectedItem) => sItem.__key !== selectedItem.__key);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
- if(selectValidation) {
|
|
|
|
|
- if(selectValidation(selectedItem)) {
|
|
|
|
|
|
|
+ let isProcessPerm = false;
|
|
|
|
|
+
|
|
|
|
|
+ if(isMultipleSelect) {
|
|
|
|
|
+ if(!maxChoice) {
|
|
|
|
|
+ throw new Error("If you want to use the \"isMultipleSelect\" prop, you must be provide \"maxChoice\" prop.");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if(_selectedItems.length < maxChoice || maxChoice === -1) {
|
|
|
|
|
+ isProcessPerm = true;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // TODO: make toast;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ _selectedItems = [];
|
|
|
|
|
+ isProcessPerm = true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if(isProcessPerm) {
|
|
|
|
|
+ if(selectValidation) {
|
|
|
|
|
+ if(selectValidation(selectedItem)) {
|
|
|
|
|
+ _selectedItems.push({
|
|
|
|
|
+ __title: selectedItem.__title,
|
|
|
|
|
+ __key: selectedItem.__key
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
_selectedItems.push({
|
|
_selectedItems.push({
|
|
|
__title: selectedItem.__title,
|
|
__title: selectedItem.__title,
|
|
|
__key: selectedItem.__key
|
|
__key: selectedItem.__key
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
- } else {
|
|
|
|
|
- _selectedItems.push({
|
|
|
|
|
- __title: selectedItem.__title,
|
|
|
|
|
- __key: selectedItem.__key
|
|
|
|
|
- });
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -682,167 +711,6 @@ function SelectBox<T>({
|
|
|
/>;
|
|
/>;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- const renderBottomSheetContent = () => {
|
|
|
|
|
- if(isLoading) {
|
|
|
|
|
- return <View
|
|
|
|
|
- style={[
|
|
|
|
|
- stylesheet.loadingContainer,
|
|
|
|
|
- loadingContainerDynamicStyle
|
|
|
|
|
- ]}
|
|
|
|
|
- >
|
|
|
|
|
- {LoadingIconComponentProp ? <LoadingIconComponentProp/> : <Loading/>}
|
|
|
|
|
- </View>;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- 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>;
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- const renderBottomSheetHeader = () => {
|
|
|
|
|
- return <View
|
|
|
|
|
- style={[
|
|
|
|
|
- stylesheet.bottomSheetHeaderContainer,
|
|
|
|
|
- bottomSheetHeaderContainerDynamicStyle
|
|
|
|
|
- ]}
|
|
|
|
|
- >
|
|
|
|
|
- <Text
|
|
|
|
|
- variant="titleMediumSize"
|
|
|
|
|
- style={[
|
|
|
|
|
- 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={() => {
|
|
|
|
|
- cancel();
|
|
|
|
|
- }}
|
|
|
|
|
- style={{
|
|
|
|
|
- ...bottomSheetCancelButtonDynamicStyle
|
|
|
|
|
- }}
|
|
|
|
|
- />
|
|
|
|
|
- <Button
|
|
|
|
|
- spreadBehaviour="stretch"
|
|
|
|
|
- title={localize("ok")}
|
|
|
|
|
- onPress={() => {
|
|
|
|
|
- ok();
|
|
|
|
|
- }}
|
|
|
|
|
- style={{
|
|
|
|
|
- ...bottomSheetOkButtonDynamicStyle
|
|
|
|
|
- }}
|
|
|
|
|
- />
|
|
|
|
|
- </View>;
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- const renderBottomSheet = () => {
|
|
|
|
|
- return <BottomSheet
|
|
|
|
|
- customKey={selectBoxKey.current}
|
|
|
|
|
- ref={bottomSheetRef}
|
|
|
|
|
- isAutoHeight={true}
|
|
|
|
|
- isActive={isActive}
|
|
|
|
|
- renderBottom={() => {
|
|
|
|
|
- return renderBottomSheetBottom();
|
|
|
|
|
- }}
|
|
|
|
|
- renderHeader={() => {
|
|
|
|
|
- return renderBottomSheetHeader();
|
|
|
|
|
- }}
|
|
|
|
|
- onClose={() => {
|
|
|
|
|
- setIsActive(false);
|
|
|
|
|
- }}
|
|
|
|
|
- >
|
|
|
|
|
- {renderBottomSheetContent()}
|
|
|
|
|
- </BottomSheet>;
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
return <View
|
|
return <View
|
|
|
style={[
|
|
style={[
|
|
|
style,
|
|
style,
|
|
@@ -876,7 +744,33 @@ function SelectBox<T>({
|
|
|
</TouchableOpacity>
|
|
</TouchableOpacity>
|
|
|
|
|
|
|
|
{renderHintText()}
|
|
{renderHintText()}
|
|
|
- {renderBottomSheet()}
|
|
|
|
|
|
|
+
|
|
|
|
|
+ <SelectSheet
|
|
|
|
|
+ LoadingIconComponentProp={LoadingIconComponentProp}
|
|
|
|
|
+ isWorkWithRealtime={isWorkWithRealtime}
|
|
|
|
|
+ mainSelectedItems={mainSelectedItems}
|
|
|
|
|
+ isMultipleSelect={isMultipleSelect}
|
|
|
|
|
+ renderOptionIcon={renderOptionIcon}
|
|
|
|
|
+ selectBoxKey={selectBoxKey.current}
|
|
|
|
|
+ bottomSheetRef={bottomSheetRef}
|
|
|
|
|
+ setSearchText={setSearchText}
|
|
|
|
|
+ searchedData={searchedData}
|
|
|
|
|
+ isSearchable={isSearchable}
|
|
|
|
|
+ keyExtractor={keyExtractor}
|
|
|
|
|
+ selectObject={selectObject}
|
|
|
|
|
+ setIsLoading={setIsLoading}
|
|
|
|
|
+ setIsActive={setIsActive}
|
|
|
|
|
+ searchText={searchText}
|
|
|
|
|
+ renderItem={renderItem}
|
|
|
|
|
+ maxChoice={maxChoice}
|
|
|
|
|
+ minChoice={minChoice}
|
|
|
|
|
+ isLoading={isLoading}
|
|
|
|
|
+ isActive={isActive}
|
|
|
|
|
+ cancel={cancel}
|
|
|
|
|
+ title={title}
|
|
|
|
|
+ data={data}
|
|
|
|
|
+ ok={ok}
|
|
|
|
|
+ />
|
|
|
</View>;
|
|
</View>;
|
|
|
};
|
|
};
|
|
|
export default forwardRef(SelectBox) as unknown as SelectBoxComponent;
|
|
export default forwardRef(SelectBox) as unknown as SelectBoxComponent;
|