UNPKG

react-native-tree-multi-select

Version:

A super-fast, customizable tree view component for React Native with multi-selection, checkboxes, and search filtering capabilities.

183 lines (179 loc) 6.34 kB
"use strict"; import React from "react"; import { View, StyleSheet, TouchableOpacity } from "react-native"; import { FlashList } from "@shopify/flash-list"; import { useTreeViewStore } from "../store/treeView.store"; import { getFilteredTreeData, getFlattenedTreeData, getInnerMostChildrenIdsInTree, handleToggleExpand, toggleCheckboxes } from "../helpers"; import { CheckboxView } from "./CheckboxView"; import { CustomExpandCollapseIcon } from "./CustomExpandCollapseIcon"; import { defaultIndentationMultiplier } from "../constants/treeView.constants"; import { useShallow } from "zustand/react/shallow"; import { typedMemo } from "../utils/typedMemo"; import { ScrollToNodeHandler } from "../handlers/ScrollToNodeHandler"; import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; const NodeList = typedMemo(_NodeList); export default NodeList; function _NodeList(props) { const { storeId, scrollToNodeHandlerRef, initialScrollNodeID, treeFlashListProps, checkBoxViewStyleProps, indentationMultiplier, CheckboxComponent, ExpandCollapseIconComponent, ExpandCollapseTouchableComponent, CustomNodeRowComponent } = props; const { expanded, initialTreeViewData, updateInnerMostChildrenIds, searchKeys, searchText } = useTreeViewStore(storeId)(useShallow(state => ({ expanded: state.expanded, initialTreeViewData: state.initialTreeViewData, updateInnerMostChildrenIds: state.updateInnerMostChildrenIds, searchKeys: state.searchKeys, searchText: state.searchText }))); const flashListRef = React.useRef(null); const [initialScrollIndex, setInitialScrollIndex] = React.useState(-1); // First we filter the tree as per the search term and keys const filteredTree = React.useMemo(() => getFilteredTreeData(initialTreeViewData, searchText.trim().toLowerCase(), searchKeys), [initialTreeViewData, searchText, searchKeys]); // Then we flatten the tree to make it "render-compatible" in a "flat" list const flattenedFilteredNodes = React.useMemo(() => getFlattenedTreeData(filteredTree, expanded), [filteredTree, expanded]); // And update the innermost children id -> required to un/select filtered tree React.useEffect(() => { const updatedInnerMostChildrenIds = getInnerMostChildrenIdsInTree(filteredTree); updateInnerMostChildrenIds(updatedInnerMostChildrenIds); }, [filteredTree, updateInnerMostChildrenIds]); const nodeRenderer = React.useCallback(({ item }) => { return /*#__PURE__*/_jsx(Node, { storeId: storeId, node: item, level: item.level || 0, checkBoxViewStyleProps: checkBoxViewStyleProps, indentationMultiplier: indentationMultiplier, CheckboxComponent: CheckboxComponent, ExpandCollapseIconComponent: ExpandCollapseIconComponent, ExpandCollapseTouchableComponent: ExpandCollapseTouchableComponent, CustomNodeRowComponent: CustomNodeRowComponent }); }, [storeId, CheckboxComponent, ExpandCollapseIconComponent, ExpandCollapseTouchableComponent, CustomNodeRowComponent, checkBoxViewStyleProps, indentationMultiplier]); return /*#__PURE__*/_jsxs(_Fragment, { children: [/*#__PURE__*/_jsx(ScrollToNodeHandler, { ref: scrollToNodeHandlerRef, storeId: storeId, flashListRef: flashListRef, flattenedFilteredNodes: flattenedFilteredNodes, setInitialScrollIndex: setInitialScrollIndex, initialScrollNodeID: initialScrollNodeID }), /*#__PURE__*/_jsx(FlashList, { ref: flashListRef, estimatedItemSize: 36, initialScrollIndex: initialScrollIndex, removeClippedSubviews: true, keyboardShouldPersistTaps: "handled", drawDistance: 50, ListHeaderComponent: /*#__PURE__*/_jsx(HeaderFooterView, {}), ListFooterComponent: /*#__PURE__*/_jsx(HeaderFooterView, {}), ...treeFlashListProps, data: flattenedFilteredNodes, renderItem: nodeRenderer })] }); } ; function HeaderFooterView() { return /*#__PURE__*/_jsx(View, { style: styles.defaultHeaderFooter }); } function getValue(isChecked, isIndeterminate) { if (isIndeterminate) { return "indeterminate"; } else if (isChecked) { return true; } else { return false; } } const Node = typedMemo(_Node); function _Node(props) { const { storeId, node, level, checkBoxViewStyleProps, indentationMultiplier = defaultIndentationMultiplier, ExpandCollapseIconComponent = CustomExpandCollapseIcon, CheckboxComponent = CheckboxView, ExpandCollapseTouchableComponent = TouchableOpacity, CustomNodeRowComponent } = props; const { isExpanded, value } = useTreeViewStore(storeId)(useShallow(state => ({ isExpanded: state.expanded.has(node.id), value: getValue(state.checked.has(node.id), // isChecked state.indeterminate.has(node.id) // isIndeterminate ) }))); const _onToggleExpand = React.useCallback(() => { handleToggleExpand(storeId, node.id); }, [storeId, node.id]); const _onCheck = React.useCallback(() => { toggleCheckboxes(storeId, [node.id]); }, [storeId, node.id]); if (!CustomNodeRowComponent) { return /*#__PURE__*/_jsxs(View, { style: [styles.nodeCheckboxAndArrowRow, { paddingStart: level * indentationMultiplier }], children: [/*#__PURE__*/_jsx(CheckboxComponent, { text: node.name, onValueChange: _onCheck, value: value, ...checkBoxViewStyleProps }), node.children?.length ? /*#__PURE__*/_jsx(ExpandCollapseTouchableComponent, { style: styles.nodeExpandableArrowTouchable, onPress: _onToggleExpand, children: /*#__PURE__*/_jsx(ExpandCollapseIconComponent, { isExpanded: isExpanded }) }) : null] }); } else { return /*#__PURE__*/_jsx(CustomNodeRowComponent, { node: node, level: level, checkedValue: value, isExpanded: isExpanded, onCheck: _onCheck, onExpand: _onToggleExpand }); } } ; const styles = StyleSheet.create({ defaultHeaderFooter: { padding: 5 }, nodeExpandableArrowTouchable: { flex: 1 }, nodeCheckboxAndArrowRow: { flex: 1, flexDirection: "row", alignItems: "center", minWidth: "100%" } }); //# sourceMappingURL=NodeList.js.map