Skip to content

Commit

Permalink
feat: NavSection Renderer component
Browse files Browse the repository at this point in the history
  • Loading branch information
devcatalin committed Sep 13, 2021
1 parent 87ac228 commit 1885c09
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import Colors from '@styles/Colors';
import styled from 'styled-components';

type BaseContainerProps = {isSelected: boolean; isHighlighted: boolean};
const BaseContainer = styled.li<BaseContainerProps>`
width: 100%;
${props => {
if (!props.isSelected && props.isHighlighted) {
return `background: ${Colors.highlightGradient};`;
}
if (props.isSelected) {
return `background: ${Colors.selectionGradient};`;
}
}};
`;

type BaseNameProps = {isSelected: boolean; isHighlighted: boolean; level: number};
const BaseName = styled.span<BaseNameProps>`
margin-left: ${props => `${props.level * 8}px`};
${props => {
if (!props.isSelected && props.isHighlighted) {
return `color: ${Colors.cyan7};`;
}
if (props.isSelected) {
return `color: ${Colors.blackPure}`;
}
return `color: ${Colors.blue10}`;
}};
`;

export const Section = {
Container: styled(BaseContainer)``,
Name: styled(BaseName)``,
};

export const ItemContainer = styled(BaseContainer)`
display: flex;
align-items: center;
`;

export const ItemName = styled(BaseName)`
cursor: pointer;
`;

export const ItemPrefix = styled.span``;

export const ItemSuffix = styled.span``;

export const ItemContextMenu = styled.span`
margin-left: auto;
`;
108 changes: 108 additions & 0 deletions src/components/organisms/NewNavigatorPane/NavSectionRenderer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import React, {useCallback, useMemo} from 'react';
import {NavSectionItemHandlers, NavSection} from '@models/navsection';
import * as S from './NavSectionRenderer.styled';

function NavSectionItem<ItemType, ScopeType>(props: {
item: ItemType;
scope: ScopeType;
handlers: NavSectionItemHandlers<ItemType, ScopeType>;
level: number;
}) {
const {item, scope, handlers, level} = props;

const name = useMemo(() => {
return handlers.getName(item, scope);
}, [handlers.getName, scope]);

const isSelected = useMemo(() => {
return Boolean(handlers.isSelected && handlers.isSelected(item, scope));
}, [handlers.isSelected, scope]);

const isHighlighted = useMemo(() => {
return Boolean(handlers.isHighlighted && handlers.isHighlighted(item, scope));
}, [handlers.isHighlighted, scope]);

return (
<S.ItemContainer
isSelected={isSelected}
isHighlighted={isHighlighted}
onClick={() => handlers.onClick && handlers.onClick(item, scope)}
>
<S.ItemName level={level} isSelected={isSelected} isHighlighted={isHighlighted}>
{name}
</S.ItemName>
</S.ItemContainer>
);
}

function NavSectionRenderer<ItemType, ScopeType>(props: {navSection: NavSection<ItemType, ScopeType>; level: number}) {
const {navSection, level} = props;
const {name, getItems, getItemsGrouped, useScope, itemHandlers, subsections} = navSection;

const scope = useScope();

const items = useMemo(() => {
if (getItems) {
return getItems(scope);
}
return undefined;
}, [scope, getItems]);

const groupedItems = useMemo(() => {
if (getItemsGrouped) {
return getItemsGrouped(scope);
}
return undefined;
}, [scope, getItemsGrouped]);

const getItemIdentifier = useCallback(
(item: ItemType) => {
if (!itemHandlers) {
return null;
}
return itemHandlers.getIdentifier(item, scope);
},
[scope, itemHandlers]
);

return (
<>
<S.Section.Container isSelected={false} isHighlighted={false}>
{name}
</S.Section.Container>
{itemHandlers &&
items &&
items.map(item => (
<NavSectionItem<ItemType, ScopeType>
key={getItemIdentifier(item)}
item={item}
scope={scope}
handlers={itemHandlers}
level={level + 1}
/>
))}
{itemHandlers &&
groupedItems &&
Object.entries(groupedItems).map(([groupName, groupItems]) => (
<React.Fragment key={groupName}>
<S.Section.Container isSelected={false} isHighlighted={false} style={{color: 'red'}}>
{groupName}
</S.Section.Container>
{groupItems.map(item => (
<NavSectionItem<ItemType, ScopeType>
key={getItemIdentifier(item)}
item={item}
scope={scope}
handlers={itemHandlers}
level={level + 2}
/>
))}
</React.Fragment>
))}
{subsections &&
subsections.map(child => <NavSectionRenderer key={child.name} navSection={child} level={level + 1} />)}
</>
);
}

export default NavSectionRenderer;

0 comments on commit 1885c09

Please sign in to comment.