import type { ReactIsland } from "@ethicdevs/react-monolith";
import React, { useCallback, useState } from "react";
import styled, { css } from "styled-components";
import type { SectionsWithPages, WithThemeSchemeProp } from "../types";
import { MenuDivider } from "../components/MenuDivider";
import { MenuItem } from "../components/MenuItem";
import { NamedColors } from "../utils/style";
interface SideMenuProps {
foo?: boolean;
currentPageSlug?: string;
currentSectionSlug?: string;
menuDefinition: SectionsWithPages;
}
const SideMenu: ReactIsland<SideMenuProps & WithThemeSchemeProp> = ({
menuDefinition,
themeScheme,
currentPageSlug = undefined,
currentSectionSlug = undefined,
}) => {
const [activeSectionSlug, setActiveSectionSlug] = useState<string | null>(
currentSectionSlug || null
);
const [activePageSlug, setActivePageSlug] = useState<string | null>(
currentPageSlug || null
);
const onMenuItemSectionClick: React.MouseEventHandler<HTMLAnchorElement> =
useCallback(
(ev) => {
ev.persist();
ev.preventDefault();
const windowPathname = new URL(window.location.href).pathname;
const windowSectionSlug = windowPathname.split("/")[2];
const linkPathname = new URL(ev.currentTarget.href).pathname;
const linkSectionSlug = linkPathname.split("/")[2];
const linkPageSlug = linkPathname.split("/")[3];
const changePage = () => {
let timeoutId = setTimeout(() => {
clearTimeout(timeoutId);
window.location.replace(linkPathname);
}, 10);
};
if (windowSectionSlug !== linkSectionSlug) {
setActiveSectionSlug(linkSectionSlug);
if (activePageSlug !== linkPageSlug) {
setActivePageSlug(linkPageSlug);
}
changePage();
} else if (
windowSectionSlug === activeSectionSlug &&
activeSectionSlug !== linkSectionSlug
) {
setActiveSectionSlug(linkSectionSlug);
if (activePageSlug !== linkPageSlug) {
setActivePageSlug(linkPageSlug);
}
changePage();
} else {
setActiveSectionSlug((prev) =>
prev == null ? linkSectionSlug : null
);
}
},
[
activeSectionSlug,
activePageSlug,
setActiveSectionSlug,
setActivePageSlug,
]
);
return (
<div style={{ width: "100%" }}>
{menuDefinition != null &&
Object.entries(menuDefinition).map(
([sectionSlug, section], idx, arr) => (
<React.Fragment key={sectionSlug}>
<StyledMenuSectionContainer
themeScheme={themeScheme}
active={sectionSlug === activeSectionSlug}
>
<>
<MenuItem
data-section
slug={sectionSlug}
section
active={sectionSlug === activeSectionSlug}
href={`/docs/${sectionSlug}/${
Object.keys(section.pagesBySlug)[0]
}`}
onClick={onMenuItemSectionClick}
themeScheme={themeScheme}
title={section.title}
>
{section.title}
</MenuItem>
{activeSectionSlug === sectionSlug &&
section.pagesBySlug != null &&
Object.entries(section.pagesBySlug).map(
([pageSlug, page]) => (
<MenuItem
key={pageSlug}
slug={pageSlug}
active={
sectionSlug === activeSectionSlug &&
pageSlug === activePageSlug
}
href={`/docs/${sectionSlug}/${pageSlug}`}
themeScheme={themeScheme}
title={page.metas.title}
>
{page.metas.title}
</MenuItem>
)
)}
</>
</StyledMenuSectionContainer>
{idx < arr.length - 1 && (
<MenuDivider themeScheme={themeScheme} />
)}
</React.Fragment>
)
)}
</div>
);
};
const hoverOrActiveCss = css<{ active?: boolean } & WithThemeSchemeProp>`
${({ themeScheme }) => css`
background-color: ${NamedColors.SIDE_MENU_SECTION_HOVER[themeScheme]};
`};
& > [data-section] {
${({ themeScheme, active = false }) => css`
border-bottom: 1px solid
${active
? NamedColors.BORDER_DEFAULT[themeScheme]
: NamedColors.SIDE_MENU_ITEM_HOVER[themeScheme]};
background-color: ${NamedColors.SIDE_MENU_ITEM_HOVER[
themeScheme
]} !important;
`};
}
`;
const StyledMenuSectionContainer = styled.div<
{ active?: boolean } & WithThemeSchemeProp
>`
width: 100%;
transition: background-color 140ms ease-in-out 0s, color 140ms ease-in-out 0s;
${({ active = false }) => active && hoverOrActiveCss};
&:hover {
${hoverOrActiveCss};
}
`;
SideMenu.displayName = "SideMenu";
export default SideMenu;