react-native-tree-selection
Version:
A high-performance and lightweight tree selection library for React Native.
124 lines • 7.48 kB
JavaScript
import { cloneDeep, isArray, isEmpty, isEqual, isNull, isString, isUndefined, } from 'lodash';
import React, { useEffect } from 'react';
import { FlatList, Image, Text, TouchableOpacity, View } from 'react-native';
import { Icons } from '../../assets';
import { Strings } from '../../constants';
import styles from './styles';
import useTreeSelect from './useTreeSelect';
const CustomImage = ({ source, style }) => {
return React.createElement(Image, { source: source, style: [styles.iconView, style] });
};
const ParentItem = React.memo(({ item, parentContainerStyles, parentTextStyles, onPressCheckbox, showChildren, renderIcon, titleKey, childKey, touchableActiveOpacity, }) => {
var _a, _b, _c;
return (React.createElement(View, { style: styles.renderContainer },
React.createElement(TouchableOpacity, { activeOpacity: touchableActiveOpacity, testID: `${item[titleKey]}-parent`, onPress: () => showChildren(item), style: parentContainerStyles !== null && parentContainerStyles !== void 0 ? parentContainerStyles : styles.parentStyles },
React.createElement(TouchableOpacity, { activeOpacity: touchableActiveOpacity, testID: `${item[titleKey]}-press`, onPress: () => {
onPressCheckbox(item);
}, style: styles.chevronContainer }, renderIcon((_a = item === null || item === void 0 ? void 0 : item.isSelected) !== null && _a !== void 0 ? _a : false, 'child')),
React.createElement(Text, { style: [styles.text, parentTextStyles] }, item[titleKey]),
Array.isArray(item[childKey]) &&
((_b = item[childKey]) === null || _b === void 0 ? void 0 : _b.length) > 0 && (React.createElement(View, { style: styles.chevronContainer }, renderIcon((_c = item === null || item === void 0 ? void 0 : item.isExpanded) !== null && _c !== void 0 ? _c : false))))));
});
const ChildItem = React.memo(({ item, childContainerStyles, childTextStyles, onPressCheckbox, titleKey, onChildPress, renderIcon, touchableActiveOpacity, }) => {
var _a;
return (React.createElement(TouchableOpacity, { activeOpacity: touchableActiveOpacity, testID: `${item[titleKey]}-child`, style: [styles.childrenContainerStyles, childContainerStyles], onPress: () => onChildPress(item) },
React.createElement(TouchableOpacity, { activeOpacity: touchableActiveOpacity, onPress: () => {
onPressCheckbox(item);
}, testID: `${item[titleKey]}-press`, style: styles.chevronContainer }, renderIcon((_a = item === null || item === void 0 ? void 0 : item.isSelected) !== null && _a !== void 0 ? _a : false, 'child')),
React.createElement(Text, { style: [styles.text, childTextStyles] }, item[titleKey])));
});
const TreeSelect = ({ data, onParentPress = (_value) => { }, onChildPress = (_value) => { }, onCheckBoxPress = ([]) => { }, leftIconStyles, rightIconStyles, parentContainerStyles, childContainerStyles, parentTextStyles, childTextStyles, autoSelectParents = true, autoSelectChildren = true, autoExpandable = false, titleKey = 'title', childKey = 'data', renderArrowOpen, renderArrowClosed, renderSelect, renderUnSelect, touchableActiveOpacity = 0.7, flatListProps, }) => {
const { listData, setListData, refresh, onPressCheckbox, showChildren } = useTreeSelect({
data,
onCheckBoxPress,
autoSelectParents,
autoSelectChildren,
childKey,
autoExpandable,
onParentPress,
});
useEffect(() => {
data && setListData(cloneDeep(data));
}, [data, setListData]);
useEffect(() => {
isEqual(childKey, titleKey) && console.warn(Strings.samePropsError);
}, [childKey, titleKey]);
const renderIcon = (status, type = 'parent') => {
const isChild = type === 'child';
let selectIcon;
if (isChild) {
selectIcon = status
? { custom: renderSelect, default: Icons.checkboxChecked }
: { custom: renderUnSelect, default: Icons.checkboxUnchecked };
}
else {
selectIcon = status
? { custom: renderArrowOpen, default: Icons.open }
: { custom: renderArrowClosed, default: Icons.close };
}
if (React.isValidElement(selectIcon.custom)) {
return selectIcon.custom;
}
const iconStyle = isChild ? rightIconStyles : leftIconStyles;
return React.createElement(CustomImage, { source: selectIcon.default, style: iconStyle });
};
/**
* This is Render tree @RecursiveFunction which calls itself if found any children.
* @FlatList is used to re-render the tree.
* This @FlatList is divided into 3 Parts:
*
* Part I - In this part all the elements are rendered which have the children.
* All The styling for the parent @Items will goes here.
*
* Part II - In this part all the elements are rendered which does not have the children.
* All The styling for the leaf children @Items will goes here.
*
* Part III - If any @Item having children's will call the @RecursiveFunction and re-render FlatList.
* All the styling between @children and @parent goes here.
*/
const renderTree = ({ item }) => {
if (isUndefined(item.isExpanded)) {
item.isExpanded = false;
}
if (isUndefined(item.isSelected)) {
item.isSelected = false;
}
const hasTitle = isString(item === null || item === void 0 ? void 0 : item[titleKey]);
const hasChildren = isArray(item === null || item === void 0 ? void 0 : item[childKey]) && !isEmpty(item[childKey]);
return (React.createElement(React.Fragment, null,
hasTitle && hasChildren && (React.createElement(ParentItem, { ...{
item,
parentContainerStyles,
parentTextStyles,
onPressCheckbox,
showChildren,
renderIcon,
titleKey,
childKey,
touchableActiveOpacity,
} })),
hasTitle && isEmpty(item === null || item === void 0 ? void 0 : item[childKey]) && (React.createElement(ChildItem, { ...{
item,
childContainerStyles,
childTextStyles,
onPressCheckbox,
titleKey,
onChildPress,
renderIcon,
touchableActiveOpacity,
} })),
!isNull(item === null || item === void 0 ? void 0 : item[childKey]) && item.isExpanded && (React.createElement(View, { style: styles.innerContainer },
React.createElement(FlatList, { data: item[childKey], renderItem: ({ item: itemName }) => {
if (!itemName.parent) {
itemName.parent = item;
}
return renderTree({ item: itemName });
} })))));
};
/**
* This is the return function which renders the JSX.
*/
return (React.createElement(FlatList, { showsVerticalScrollIndicator: false, ...flatListProps, contentContainerStyle: styles.containerStyle, data: listData, renderItem: renderTree, keyExtractor: (_item, index) => index.toString(), extraData: refresh }));
};
export default TreeSelect;
//# sourceMappingURL=TreeSelect.js.map