UNPKG

react-native-tree-selection

Version:

A high-performance and lightweight tree selection library for React Native.

124 lines 7.48 kB
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