@kenshooui/react-tree
Version:
React Tree is a straight forward component that allows a user to display and manage a hierarchical structure of items in a clear and comfortable way.
136 lines (125 loc) • 3.63 kB
JavaScript
/** @jsx jsx */
import { jsx } from "@emotion/core";
import React from "react";
import { defaultStyles } from "./styles/styles";
import ItemDefault from "./item/item";
import HeaderDefault from "./header/header";
import InputDefault from "./input/input";
import NoResultsDefault from "./no_results/no_results";
import useLeavesManager from "./hooks/use_leaves_manager";
import useItemCallbacks from "./hooks/use_item_callbacks";
import TreeContainerRenderer from "./tree_container/tree_container";
import ItemsRenderer from "./items/items";
import useContainerHeight from "./hooks/use_components_refs";
const DEFAULT_WIDTH = 230;
const DEFAULT_HEIGHT = 300;
const PIXEL_SUFFIX = "px";
const Tree = props => {
const {
structure = [],
title,
onSelect,
width,
height,
styles,
className,
noResultsText = "No matching results",
headerRenderer: Header = HeaderDefault,
backIconRenderer,
inputRenderer: Input = InputDefault,
inputIconRenderer,
clearIconRenderer,
noResultsRenderer: NoResults = NoResultsDefault,
noResultsIconRenderer,
itemRenderer: Item = ItemDefault,
itemsRenderer: Items = ItemsRenderer,
forwardIconRenderer,
treeContainerRenderer: TreeContainer = TreeContainerRenderer,
customItemsRenderer,
selectedItem
} = props;
const getStyles = (key, props = {}) => {
const base = defaultStyles[key](props);
base.boxSizing = "border-box";
const custom = props.styles && props.styles[key];
return custom ? custom(base, props) : base;
};
const {
containerRef,
headerRef,
inputRef,
itemsHeight
} = useContainerHeight();
const { onClick, onBackClick, currentDepth, parents } = useItemCallbacks({
onSelect
});
const { searchTerm, onInputChange, leaves } = useLeavesManager({
structure,
parents,
currentDepth
});
return (
<TreeContainer
containerRef={containerRef}
getStyles={getStyles}
styles={styles}
width={(width || DEFAULT_WIDTH) + PIXEL_SUFFIX}
height={(height || DEFAULT_HEIGHT) + PIXEL_SUFFIX}
>
<Header
headerRef={headerRef}
parents={parents}
title={title}
onClick={onBackClick}
getStyles={getStyles}
styles={styles}
backIconRenderer={backIconRenderer}
>
{title}
</Header>
<Input
inputRef={inputRef}
getStyles={getStyles}
styles={styles}
searchTerm={searchTerm}
onInputChange={onInputChange}
inputIconRenderer={inputIconRenderer}
clearIconRenderer={clearIconRenderer}
/>
{customItemsRenderer ? (
React.cloneElement(customItemsRenderer, {
leaves,
searchTerm,
onClick,
selectedItem,
forwardIconRenderer
})
) : (
<Items styles={styles} getStyles={getStyles} height={itemsHeight}>
{leaves &&
leaves.length > 0 &&
leaves.map(item => (
<Item
getStyles={getStyles}
searchTerm={searchTerm}
item={item}
onClick={onClick}
forwardIconRenderer={forwardIconRenderer}
selectedItem={selectedItem}
/>
))}
</Items>
)}
{leaves && leaves.length === 0 && (
<NoResults
height={itemsHeight}
text={noResultsText}
getStyles={getStyles}
styles={styles}
noResultsIconRenderer={noResultsIconRenderer}
/>
)}
</TreeContainer>
);
};
export default Tree;