Skip to content

Commit

Permalink
Merge branch 'main' into ft/climatemapped_hero
Browse files Browse the repository at this point in the history
  • Loading branch information
koechkevin committed Oct 22, 2024
2 parents b8635a2 + 946c931 commit 8957bd4
Show file tree
Hide file tree
Showing 10 changed files with 332 additions and 175 deletions.
2 changes: 1 addition & 1 deletion apps/climatemappedafrica/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@
"@emotion/styled": "catalog:",
"@hurumap/core": "workspace:*",
"@hurumap/next": "workspace:*",
"@mui/lab": "catalog:mui-styles",
"@mui/material": "catalog:mui-styles",
"@mui/styles": "catalog:mui-styles",
"@mui/utils": "catalog:mui-styles",
"@mui/x-tree-view": "catalog:",
"@next/env": "catalog:",
"@payloadcms/bundler-webpack": "catalog:",
"@payloadcms/db-mongodb": "catalog:",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import PropTypes from "prop-types";
import React, { useRef } from "react";

import useStyles from "./useStyles";

import Profile from "@/climatemappedafrica/components/HURUmap/Panel/Profile";
import TreeView from "@/climatemappedafrica/components/HURUmap/TreeView";

function RichData({ primaryProfile, ...props }) {
const classes = useStyles(props);
const profileRef = useRef();

const handleLabelClick = (id) => {
Expand All @@ -22,7 +19,16 @@ function RichData({ primaryProfile, ...props }) {
<TreeView
items={primaryProfile.items}
onLabelClick={handleLabelClick}
classes={{ root: classes.treeView }}
sx={(theme) => ({
width: `calc((100vw - ${theme.widths.values.lg}px)/2 + 79px)`,
minWidth: theme.typography.pxToRem(300),
paddingTop: theme.typography.pxToRem(76),
flexShrink: 0,
top: theme.typography.pxToRem(110),
bottom: 0,
position: "fixed",
left: 0,
})}
/>
<Profile
{...props}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,6 @@ const useStyles = makeStyles(
background: palette.background.default,
display: "flex",
},
treeView: {
width: `calc((100vw - ${widths.values.lg}px)/2 + 79px)`,
minWidth: typography.pxToRem(300),
paddingTop: typography.pxToRem(76),
flexShrink: 0,
top: typography.pxToRem(110),
bottom: 0,
position: "fixed",
left: 0,
},
}),
);

Expand Down
210 changes: 210 additions & 0 deletions apps/climatemappedafrica/src/components/HURUmap/TreeView/TreeView.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
import { Box, SvgIcon } from "@mui/material";
import { alpha, styled } from "@mui/material/styles";
import { SimpleTreeView } from "@mui/x-tree-view/SimpleTreeView";
import {
TreeItem2Checkbox,
TreeItem2Content,
TreeItem2GroupTransition,
TreeItem2IconContainer,
TreeItem2Label,
TreeItem2Root,
} from "@mui/x-tree-view/TreeItem2";
import { TreeItem2Icon } from "@mui/x-tree-view/TreeItem2Icon";
import { TreeItem2Provider } from "@mui/x-tree-view/TreeItem2Provider";
import { useTreeItem2 } from "@mui/x-tree-view/useTreeItem2";
import clsx from "clsx";
import PropTypes from "prop-types";
import React from "react";

import CheckIcon from "@/climatemappedafrica/assets/icons/checked.svg";
import slugify from "@/climatemappedafrica/utils/slugify";

const CustomTreeItemContent = styled(TreeItem2Content)(({ theme }) => ({
background: "inherit",
borderRadius: 0,
borderBottom: `1px solid transparent`,
borderRight: `2px solid transparent`,
padding: 0,
paddingRight: theme.spacing(2.5),
"&:hover": {
background: "inherit",
},
"&.expanded": {
backgroundColor: theme.palette.background.default,
borderRight: `2px solid ${theme.palette.primary.main}`,
borderBottom: `1px solid ${theme.palette.grey.main}`,
},
}));

const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) {
const { id, itemId, label, disabled, children, ...other } = props;

const {
getRootProps,
getContentProps,
getIconContainerProps,
getCheckboxProps,
getLabelProps,
getGroupTransitionProps,
status,
} = useTreeItem2({ id, itemId, children, label, disabled, rootRef: ref });

return (
<TreeItem2Provider itemId={itemId}>
<TreeItem2Root {...getRootProps(other)}>
<CustomTreeItemContent
{...getContentProps({
className: clsx("content", {
expanded: status.expanded,
selected: status.selected,
focused: status.focused,
}),
sx: (theme) => ({
...(!children && {
pr: 0,
"&: hover": {
background: alpha(theme.palette.common.black, 0.04),
},
}),
}),
})}
>
<TreeItem2Checkbox {...getCheckboxProps()} />
<TreeItem2Label
{...getLabelProps({
sx: (theme) => ({
...theme.typography.caption,
height: 38,
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
fontWeight: 500,
letterSpacing: 0.6,
...(!children && {
fontWeight: 300,
paddingRight: 2.5,
}),
}),
})}
/>
<TreeItem2IconContainer
{...getIconContainerProps({
sx: {
...(!children && { display: "none" }),
},
})}
>
<TreeItem2Icon status={status} />
</TreeItem2IconContainer>
</CustomTreeItemContent>
{children && (
<TreeItem2GroupTransition {...getGroupTransitionProps()} />
)}
</TreeItem2Root>
</TreeItem2Provider>
);
});

function CollapseIcon({ sx, ...props }) {
return (
<SvgIcon
component={CheckIcon}
inheritViewBox
{...props}
sx={[
{
fill: "#666666",
},
// TODO(kilemensi): Review our use of `sx`` to ensure we folllow
// https://mui.com/system/getting-started/the-sx-prop/#passing-the-sx-prop
...(Array.isArray(sx) ? sx : [sx]),
]}
/>
);
}

function ExpandIcon({ sx, ...props }) {
return (
<CollapseIcon
{...props}
sx={[
(theme) => ({
fill: theme.palette.grey.main,
}),
...(Array.isArray(sx) ? sx : [sx]),
]}
/>
);
}

const TreeView = React.forwardRef(function TreeView(props, ref) {
const { items, onLabelClick, sx, ...others } = props;

const handleItemClick = (e, itemId) => {
e.preventDefault();

if (onLabelClick) {
onLabelClick(itemId);
}
};
if (!items?.length) {
return null;
}
return (
<Box
{...others}
sx={[
({ palette }) => ({
textAlign: "right",
background: palette.background.paper,
}),
...(Array.isArray(sx) ? sx : [sx]),
]}
ref={ref}
>
<SimpleTreeView
slots={{
collapseIcon: CollapseIcon,
expandIcon: ExpandIcon,
}}
onItemClick={handleItemClick}
>
{items.map((item) => {
const itemId = slugify(item.title);

return (
<CustomTreeItem itemId={itemId} key={itemId} label={item.title}>
{item.children.map((child) => {
const childId = slugify(`${itemId}-${child.title}`);

return (
<CustomTreeItem
itemId={childId}
key={childId}
label={child.title}
/>
);
})}
</CustomTreeItem>
);
})}
</SimpleTreeView>
</Box>
);
});

TreeView.propTypes = {
items: PropTypes.arrayOf(
PropTypes.shape({
title: PropTypes.string,
children: PropTypes.arrayOf(
PropTypes.shape({
title: PropTypes.string,
}),
),
}),
),
onLabelClick: PropTypes.func,
};

export default TreeView;
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<TreeView /> renders unchanged 1`] = `
<div>
<div
class="MuiBox-root css-h6u23h"
>
<ul
aria-multiselectable="false"
class="MuiSimpleTreeView-root css-rejl51-MuiSimpleTreeView-root"
id=":r0:"
role="tree"
style="--TreeView-itemChildrenIndentation: 12px;"
>
<li
aria-expanded="false"
class="css-1uhp40g-MuiTreeItem2-root"
id=":r0:-annual-temperature"
role="treeitem"
tabindex="0"
>
<div
class="content css-tbaszv-MuiTreeItem2-content"
>
<div
class="css-d6m21r-MuiTreeItem2-label"
>
Annual Temperature
</div>
<div
class="css-19d0qwr-MuiTreeItem2-iconContainer"
>
<div
aria-hidden="true"
class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-1ahhuu0-MuiSvgIcon-root"
focusable="false"
/>
</div>
</div>
</li>
<li
aria-expanded="false"
class="css-1uhp40g-MuiTreeItem2-root"
id=":r0:-temperature-variation"
role="treeitem"
tabindex="-1"
>
<div
class="content css-tbaszv-MuiTreeItem2-content"
>
<div
class="css-d6m21r-MuiTreeItem2-label"
>
Temperature Variation
</div>
<div
class="css-19d0qwr-MuiTreeItem2-iconContainer"
>
<div
aria-hidden="true"
class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-1ahhuu0-MuiSvgIcon-root"
focusable="false"
/>
</div>
</div>
</li>
</ul>
</div>
</div>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { createRender } from "@commons-ui/testing-library";
import React from "react";

import TreeView from ".";

import theme from "@/climatemappedafrica/theme";

// eslint-disable-next-line testing-library/render-result-naming-convention
const render = createRender({ theme });

const defaultProps = {
items: [
{
title: "Annual Temperature",
children: [
{
title: "Annual Temperature",
},
],
},
{
title: "Temperature Variation",
children: [
{
title: "Decadal Temperature Variation",
},
],
},
],
};

describe("<TreeView />", () => {
it("renders unchanged", () => {
const { container } = render(<TreeView {...defaultProps} />);
expect(container).toMatchSnapshot();
});
});
Loading

0 comments on commit 8957bd4

Please sign in to comment.