Skip to content

Commit 1700429

Browse files
authored
Support Material-UI tree (#143)
* Support Material-UI tree * failed trial to pass ref * fix paddings * changes after review * changes after second review * renaming
1 parent ab8d4da commit 1700429

24 files changed

+751
-39
lines changed

packages/core/src/header/header.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ export const BackIconRenderer = () => <>⬅️</>;
66

77
const Header = props => {
88
const {
9+
headerRef,
910
parents = [],
1011
onClick,
1112
title = "",
1213
getStyles,
1314
backIconRenderer: BackIcon = BackIconRenderer
1415
} = props;
1516
return (
16-
<div css={getStyles("header", props)}>
17+
<div ref={headerRef} css={getStyles("header", props)}>
1718
{parents.length > 0 && (
1819
<>
1920
<span css={getStyles("headerBackIcon", props)} onClick={onClick}>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { useRef } from "react";
2+
3+
const useComponentsRefs = () => {
4+
const containerRef = useRef();
5+
const headerRef = useRef();
6+
const inputRef = useRef();
7+
8+
const itemsHeight =
9+
(containerRef?.current?.clientHeight || 0) -
10+
(headerRef?.current?.clientHeight || 0) -
11+
(inputRef?.current?.clientHeight || 0);
12+
13+
return { containerRef, headerRef, inputRef, itemsHeight };
14+
};
15+
16+
export default useComponentsRefs;

packages/core/src/hooks/use_leaves_manager.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ const useLeavesManager = ({ structure, parents, currentDepth }) => {
1010
const [searchTerm, setSearchTerm] = useState("");
1111
const [leaves, setLeaves] = useState([]);
1212

13+
const onInputChange = event => setSearchTerm(event.target.value || "");
14+
1315
useEffect(() => {
1416
const leaves = structure
1517
.filter(
@@ -22,7 +24,7 @@ const useLeavesManager = ({ structure, parents, currentDepth }) => {
2224
setLeaves(removeDuplicateLeafs(leaves));
2325
}, [searchTerm, parents, currentDepth]);
2426

25-
return { searchTerm, setSearchTerm, leaves };
27+
return { searchTerm, setSearchTerm, onInputChange, leaves };
2628
};
2729

2830
export default useLeavesManager;

packages/core/src/input/input.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,21 @@ export const InputIconRenderer = () => <>🔍</>;
66

77
const Input = props => {
88
const {
9+
inputRef,
910
searchTerm,
10-
setSearchTerm,
11+
onInputChange,
1112
getStyles,
1213
inputIconRenderer: InputIcon = InputIconRenderer
1314
} = props;
1415
return (
15-
<div css={getStyles("inputWrapper", props)}>
16+
<div ref={inputRef} css={getStyles("inputWrapper", props)}>
1617
<span css={getStyles("searchInput", props)}>
1718
<InputIcon />
1819
</span>
1920
<input
2021
css={getStyles("input", props)}
2122
value={searchTerm}
22-
onChange={e => setSearchTerm(e.target.value)}
23+
onChange={onInputChange}
2324
/>
2425
</div>
2526
);

packages/core/src/items/items.js

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/** @jsx jsx */
2+
import { jsx } from "@emotion/core";
3+
import React from "react";
4+
5+
const ItemsRenderer = props => {
6+
const {
7+
getStyles,
8+
children
9+
} = props;
10+
return (
11+
<div css={getStyles("items", props)}>
12+
{children}
13+
</div>
14+
);
15+
};
16+
17+
export default ItemsRenderer;

packages/core/src/items/itemsStyle.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export default () => ({
2-
maxHeight: "203px",
1+
export default ({ height }) => ({
2+
maxHeight: height,
33
overflowY: "auto"
44
});

packages/core/src/no_results/noResultsStyle.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
export const css = () => ({
1+
export const css = ({ height }) => ({
22
display: "flex",
33
flexDirection: "column",
44
alignItems: "center",
5-
marginTop: "30px"
5+
justifyContent: "center",
6+
height: height
67
});
78

89
export const icon = () => ({

packages/core/src/styles/styles.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import treeCss from "../treeStyle";
1+
import containerCss from "../tree_container/treeContainerStyle";
22
import {
33
wrapperCss as headerWrapperCss,
44
backIconCss as headerBackIconCss
@@ -22,7 +22,7 @@ import {
2222
} from "../no_results/noResultsStyle";
2323

2424
export const defaultStyles = {
25-
tree: treeCss,
25+
container: containerCss,
2626
header: headerWrapperCss,
2727
headerBackIcon: headerBackIconCss,
2828
item: itemCss,

packages/core/src/tree.js

+40-16
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,32 @@ import NoResultsDefault from "./no_results/no_results";
1010

1111
import useLeavesManager from "./hooks/use_leaves_manager";
1212
import useItemCallbacks from "./hooks/use_item_callbacks";
13+
import TreeContainerRenderer from "./tree_container/tree_container";
14+
import ItemsRenderer from "./items/items";
15+
import useContainerHeight from "./hooks/use_components_refs";
16+
17+
const DEFAULT_WIDTH = 230;
18+
const DEFAULT_HEIGHT = 300;
19+
const PIXEL_SUFFIX = "px";
1320

1421
const Tree = props => {
1522
const {
1623
structure = [],
1724
title,
1825
onSelect,
19-
className,
26+
width,
27+
height,
2028
noResultsText = "No matching results",
21-
styles,
2229
headerRenderer: Header = HeaderDefault,
2330
backIconRenderer,
2431
inputRenderer: Input = InputDefault,
2532
inputIconRenderer,
2633
noResultsRenderer: NoResults = NoResultsDefault,
2734
noResultsIconRenderer,
2835
itemRenderer: Item = ItemDefault,
29-
forwardIconRenderer
36+
itemsRenderer: Items = ItemsRenderer,
37+
forwardIconRenderer,
38+
treeContainerRenderer: TreeContainer = TreeContainerRenderer
3039
} = props;
3140

3241
const getStyles = (key, props = {}) => {
@@ -36,19 +45,32 @@ const Tree = props => {
3645
return custom ? custom(base, props) : base;
3746
};
3847

48+
const {
49+
containerRef,
50+
headerRef,
51+
inputRef,
52+
itemsHeight
53+
} = useContainerHeight();
54+
3955
const { onClick, onBackClick, currentDepth, parents } = useItemCallbacks(
4056
onSelect
4157
);
4258

43-
const { searchTerm, setSearchTerm, leaves } = useLeavesManager({
59+
const { searchTerm, onInputChange, leaves } = useLeavesManager({
4460
structure,
4561
parents,
4662
currentDepth
4763
});
4864

4965
return (
50-
<div css={getStyles("tree", props)}>
66+
<TreeContainer
67+
containerRef={containerRef}
68+
getStyles={getStyles}
69+
width={(width || DEFAULT_WIDTH) + PIXEL_SUFFIX}
70+
height={(height || DEFAULT_HEIGHT) + PIXEL_SUFFIX}
71+
>
5172
<Header
73+
headerRef={headerRef}
5274
parents={parents}
5375
title={title}
5476
onClick={onBackClick}
@@ -58,12 +80,13 @@ const Tree = props => {
5880
{title}
5981
</Header>
6082
<Input
83+
inputRef={inputRef}
6184
getStyles={getStyles}
6285
searchTerm={searchTerm}
63-
setSearchTerm={setSearchTerm}
86+
onInputChange={onInputChange}
6487
inputIconRenderer={inputIconRenderer}
6588
/>
66-
<div css={getStyles("items", props)}>
89+
<Items getStyles={getStyles} height={itemsHeight}>
6790
{leaves &&
6891
leaves.length > 0 &&
6992
leaves.map(item => (
@@ -75,15 +98,16 @@ const Tree = props => {
7598
forwardIconRenderer={forwardIconRenderer}
7699
/>
77100
))}
78-
{leaves && leaves.length === 0 && (
79-
<NoResults
80-
text={noResultsText}
81-
getStyles={getStyles}
82-
noResultsIconRenderer={noResultsIconRenderer}
83-
/>
84-
)}
85-
</div>
86-
</div>
101+
</Items>
102+
{leaves && leaves.length === 0 && (
103+
<NoResults
104+
height={itemsHeight}
105+
text={noResultsText}
106+
getStyles={getStyles}
107+
noResultsIconRenderer={noResultsIconRenderer}
108+
/>
109+
)}
110+
</TreeContainer>
87111
);
88112
};
89113

packages/core/src/treeStyle.js renamed to packages/core/src/tree_container/treeContainerStyle.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
export default () => ({
2-
width: "230px",
3-
height: "280px",
1+
export default ({ width, height }) => ({
2+
width: width,
3+
height: height,
44
backgroundColor: "#F8F9FA",
55
boxShadow: "0 6px 10px 0 rgba(27, 32, 70, 0.09)",
66
border: "1px solid #E1E4EB",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/** @jsx jsx */
2+
import { jsx } from "@emotion/core";
3+
import React from "react";
4+
5+
const TreeContainerRenderer = props => {
6+
const { containerRef, getStyles, children } = props;
7+
return (
8+
<div ref={containerRef} css={getStyles("container", props)}>
9+
{children}
10+
</div>
11+
);
12+
};
13+
14+
export default TreeContainerRenderer;

packages/docs/stories/core.stories.js

+79-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,28 @@
11
import React from "react";
22
import Tree from "@kenshooui/react-tree";
3+
import MaterialTree from "@kenshooui/material-tree";
4+
import makeStyles from "@material-ui/core/styles/makeStyles";
5+
6+
const useStyles = makeStyles({
7+
wrapper: {
8+
padding: 40,
9+
display: "flex",
10+
justifyContent: "start",
11+
alignItems: "start"
12+
},
13+
item: {
14+
display: "flex",
15+
alignItems: "center",
16+
marginRight: 25,
17+
flexDirection: "column"
18+
},
19+
title: {
20+
fontSize: 16,
21+
color: "#747070",
22+
marginBottom: 16,
23+
fontWeight: "bold"
24+
}
25+
});
326

427
export default {
528
title: "Tree",
@@ -29,14 +52,62 @@ const structure = [
2952
["Keywords", "one level"]
3053
];
3154

32-
export const Basic = () => (
33-
<Tree
34-
structure={structure}
35-
title={"Choose an item"}
36-
onSelect={item => alert(item)}
37-
/>
38-
);
55+
export const Basic = () => {
56+
const classes = useStyles();
57+
return (
58+
<div className={classes.wrapper}>
59+
<div className={classes.item}>
60+
<div className={classes.title}>Default Dimensions</div>
61+
<Tree
62+
structure={structure}
63+
title={"Choose an item"}
64+
onSelect={item => alert(item)}
65+
/>
66+
</div>
67+
<div className={classes.item}>
68+
<div className={classes.title}>Custom Dimensions</div>
69+
<Tree
70+
structure={structure}
71+
title={"Choose an item"}
72+
onSelect={item => alert(item)}
73+
width={200}
74+
height={200}
75+
/>
76+
</div>
77+
</div>
78+
);
79+
};
80+
81+
export const MaterialTheme = () => {
82+
const classes = useStyles();
83+
return (
84+
<div className={classes.wrapper}>
85+
<div className={classes.item}>
86+
<div className={classes.title}>Default Dimensions</div>
87+
<MaterialTree
88+
structure={structure}
89+
title={"Choose an item"}
90+
onSelect={item => alert(item)}
91+
/>
92+
</div>
93+
<div className={classes.item}>
94+
<div className={classes.title}>Custom Dimensions</div>
95+
<MaterialTree
96+
structure={structure}
97+
title={"Choose an item"}
98+
onSelect={item => alert(item)}
99+
width={250}
100+
height={350}
101+
/>
102+
</div>
103+
</div>
104+
);
105+
};
39106

40107
Basic.story = {
41-
name: "basic configuration"
108+
name: "Basic configuration"
109+
};
110+
111+
MaterialTheme.story = {
112+
name: "Material Theme"
42113
};
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "@kenshooui/material-tree",
3+
"version": "1.0.0",
4+
"main": "dist/material-tree.cjs.js",
5+
"module": "dist/material-tree.esm.js",
6+
"scripts": {},
7+
"repository": "https://github.com/kenshoo/react-tree.git",
8+
"author": "ui@kenshoo.com",
9+
"license": "MIT",
10+
"peerDependencies": {
11+
"@kenshooui/react-tree": "^1.0.0",
12+
"@material-ui/core": "^4.11.2",
13+
"@material-ui/icons": "^4.11.2",
14+
"react": "^16.12.0"
15+
},
16+
"devDependencies": {
17+
"@material-ui/core": "^4.11.2",
18+
"@material-ui/icons": "^4.11.2",
19+
"react": "^16.12.0"
20+
},
21+
"dependencies": {}
22+
}

0 commit comments

Comments
 (0)