Skip to content

Basics #60

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
module.exports = {
plugins: ["emotion"],
presets: ["@babel/preset-env", "@babel/preset-react"]
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"postinstall": "preconstruct dev",
"build": "preconstruct build",
"test": "jest --coverage",
"storybook": "yarn workspace @kenshooui/react-tree-docs storybook",
"prettier": "prettier --check ./packages/**/*.js --ignore-path .gitignore",
"prettier:fix": "prettier --check ./packages/**/*.js --ignore-path .gitignore --write",
"release": "auto shipit"
Expand Down
6 changes: 5 additions & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,9 @@
"devDependencies": {
"react": "^16.12.0"
},
"scripts": {}
"scripts": {},
"dependencies": {
"@emotion/core": "^10.0.28",
"classnames": "^2.2.6"
}
}
30 changes: 30 additions & 0 deletions packages/core/src/header/header.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/** @jsx jsx */
import { jsx } from "@emotion/core";
import React from "react";

export const BackIconRenderer = () => <>⬅️</>;

const Header = props => {
const {
parents = [],
onClick,
title = "",
getStyles,
backIconRenderer: BackIcon = BackIconRenderer
} = props;
return (
<div css={getStyles("header", props)}>
{parents.length > 0 && (
<>
<span css={getStyles("headerBackIcon", props)} onClick={onClick}>
<BackIcon />
</span>
{parents[parents.length - 1]}
</>
)}
{parents.length === 0 && <>{title}</>}
</div>
);
};

export default Header;
11 changes: 11 additions & 0 deletions packages/core/src/header/headerStyle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const wrapperCss = () => ({
height: "40px",
display: "flex",
alignItems: "center",
padding: "0 6px"
});

export const backIconCss = () => ({
marginRight: "3px",
cursor: "pointer"
});
31 changes: 31 additions & 0 deletions packages/core/src/hooks/use_item_callbacks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { useState } from "react";

const useItemCallbacks = onSelect => {
const [currentDepth, setCurrentDepth] = useState(0);
const [parents, setParents] = useState([]);

const onClick = (label, item, hasChild) => {
if (hasChild) {
setParents(parents.concat(label));
setCurrentDepth(currentDepth + 1);
} else {
onSelect(item);
}
};

const onBackClick = () => {
setParents(parents.filter((parent, index) => index < parents.length - 1));
setCurrentDepth(currentDepth - 1);
};

return {
onClick,
onBackClick,
currentDepth,
setCurrentDepth,
parents,
setParents
};
};

export default useItemCallbacks;
28 changes: 28 additions & 0 deletions packages/core/src/hooks/use_leaves_manager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {
containsAllParents,
filterBySearchTerm,
buildLeafForItemRenderer,
removeDuplicateLeafs
} from "../util";
import { useState, useEffect } from "react";

const useLeavesManager = ({ structure, parents, currentDepth }) => {
const [searchTerm, setSearchTerm] = useState("");
const [leaves, setLeaves] = useState([]);

useEffect(() => {
const leaves = structure
.filter(
leaf =>
filterBySearchTerm(leaf, searchTerm) &&
containsAllParents(leaf, parents)
)
.map(leaf => buildLeafForItemRenderer(leaf, currentDepth, searchTerm));

setLeaves(removeDuplicateLeafs(leaves));
}, [searchTerm, parents, currentDepth]);

return { searchTerm, setSearchTerm, leaves };
};

export default useLeavesManager;
6 changes: 2 additions & 4 deletions packages/core/src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import React from "react";
import Tree from "./tree";

const HelloWorld = () => <div>Hello World</div>;

export default HelloWorld;
export default Tree;
28 changes: 28 additions & 0 deletions packages/core/src/input/input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/** @jsx jsx */
import { jsx } from "@emotion/core";
import React from "react";

export const InputIconRenderer = () => <>🔍</>;

const Input = props => {
const {
searchTerm,
setSearchTerm,
getStyles,
inputIconRenderer: InputIcon = InputIconRenderer
} = props;
return (
<div css={getStyles("inputWrapper", props)}>
<span css={getStyles("searchInput", props)}>
<InputIcon />
</span>
<input
css={getStyles("input", props)}
value={searchTerm}
onChange={e => setSearchTerm(e.target.value)}
/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't there a clear input here at some point?

</div>
);
};

export default Input;
27 changes: 27 additions & 0 deletions packages/core/src/input/inputStyle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export const css = () => ({
width: "100%",
height: "35px",
paddingLeft: "35px",
border: "1px solid #cfd1d2",
borderRight: "none",
borderLeft: "none",
backgroundColor: "#F8F9FA",

"&:focus": {
outline: "none !important"
},

"&:active": {
outline: "none !important"
}
});

export const searchIconCss = () => ({
position: "absolute",
top: "8px",
left: "8px"
});

export const wrapperCss = () => ({
position: "relative"
});
7 changes: 7 additions & 0 deletions packages/core/src/item/basic_item.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from "react";

const BasicItem = ({ label = "" }) => {
return <span>{label}</span>;
};

export default BasicItem;
54 changes: 54 additions & 0 deletions packages/core/src/item/item.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/** @jsx jsx */
import { jsx } from "@emotion/core";
import React from "react";

import SearchedItem from "./searched_item/searched_item";
import BasicItem from "./basic_item";

export const ForwardIconRenderer = () => <>➡️</>;

const ItemRenderer = props => {
const {
getStyles,
searchTerm = "",
item: { item, hasChild, currentDepth } = {
item: [""],
hasChild: false,
currentDepth: 0
},
onClick,
forwardIconRenderer: ForwardIcon = ForwardIconRenderer
} = props;
const searchIndex = item[item.length - 1]
.toLowerCase()
.indexOf(searchTerm.trim().toLowerCase());
return (
<div
onClick={() => onClick(item[currentDepth], item, hasChild)}
css={getStyles("item", props)}
>
{searchTerm !== "" && (
<SearchedItem
item={item}
searchIndex={searchIndex}
searchTerm={searchTerm.trim()}
getStyles={getStyles}
/>
)}
{searchTerm === "" && (
<BasicItem
label={item[currentDepth]}
searchIndex={searchIndex}
searchTerm={searchTerm.trim()}
/>
)}
{hasChild && (
<span css={getStyles("forwardIcon", props)}>
<ForwardIcon />
</span>
)}
</div>
);
};

export default ItemRenderer;
20 changes: 20 additions & 0 deletions packages/core/src/item/itemStyle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export const css = props => ({
display: "flex",
justifyContent: "space-between",
alignItems: "center",
cursor: "pointer",
height: props.searchTerm !== "" ? "50px" : "30px",
marginTop: "3px",
padding: "0 6px",
fontSize: "14px",

"&:hover": {
backgroundColor: "#ECEEF3"
},

"&:active": {
backgroundColor: "#E1E4EB"
}
});

export const forwardIconCss = () => ({});
13 changes: 13 additions & 0 deletions packages/core/src/item/searched_item/searchedItemStyle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export const initialCss = props => ({
color: "#545769"
});

export const highlightCss = props => ({
fontWeight: 600,
color: "#2020e1"
});

export const parentsCss = props => ({
color: "#98A1B8",
marginTop: "2px"
});
28 changes: 28 additions & 0 deletions packages/core/src/item/searched_item/searched_item.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/** @jsx jsx */
import { jsx } from "@emotion/core";
import React from "react";

const SearchedItem = props => {
const { item = [""], searchIndex = 0, searchTerm = "", getStyles } = props;
const leaf = item[item.length - 1];
const parents = item.slice(0, item.length - 1).join(" / ");

return (
<div>
<div>
<span css={getStyles("searchItemInitial", props)}>
{leaf.substring(0, searchIndex)}
</span>
<span css={getStyles("highlight", props)}>
{leaf.substring(searchIndex, searchIndex + searchTerm.length)}
</span>
<span css={getStyles("searchItemInitial", props)}>
{leaf.substring(searchIndex + searchTerm.length)}
</span>
</div>
<div css={getStyles("parents", props)}>{parents}</div>
</div>
);
};

export default SearchedItem;
4 changes: 4 additions & 0 deletions packages/core/src/items/itemsStyle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export default () => ({
maxHeight: "203px",
overflowY: "auto"
});
15 changes: 15 additions & 0 deletions packages/core/src/no_results/noResultsStyle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const css = () => ({
display: "flex",
flexDirection: "column",
alignItems: "center",
marginTop: "30px"
});

export const icon = () => ({
fontSize: "20px",
marginBottom: "5px"
});

export const text = () => ({
fontSize: "14px"
});
23 changes: 23 additions & 0 deletions packages/core/src/no_results/no_results.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/** @jsx jsx */
import { jsx } from "@emotion/core";
import React from "react";

export const NoResultsIconRenderer = () => <>⚠️</>;

const NoResults = props => {
const {
text,
getStyles,
noResultsIconRenderer: NoResultsIcon = NoResultsIconRenderer
} = props;
return (
<div css={getStyles("noResults", props)}>
<div css={getStyles("noResultsIcon", props)}>
<NoResultsIcon />
</div>
<div css={getStyles("noResultsText", props)}>{text}</div>
</div>
);
};

export default NoResults;
Loading