ant-design/.dumi/theme/slots/Header/Navigation.tsx

278 lines
6.6 KiB
TypeScript

import * as React from 'react';
import { FormattedMessage, Link, useFullSidebarData, useLocation } from 'dumi';
import type { MenuProps } from 'antd';
import { Menu } from 'antd';
import { MenuOutlined } from '@ant-design/icons';
import { css } from '@emotion/react';
import { getEcosystemGroup } from './More';
import * as utils from '../../utils';
import type { SharedProps } from './interface';
import useSiteToken from '../../../hooks/useSiteToken';
import useLocale from '../../../hooks/useLocale';
// ============================= Theme =============================
const locales = {
cn: {
design: '设计',
development: '研发',
components: '组件',
resources: '资源',
blog: '博客',
},
en: {
design: 'Design',
development: 'Development',
components: 'Components',
resources: 'Resources',
blog: 'Blog',
},
};
// ============================= Style =============================
const useStyle = () => {
const { token } = useSiteToken();
const { antCls, iconCls, fontFamily, headerHeight, menuItemBorder, colorPrimary } = token;
return {
nav: css`
height: 100%;
font-size: 14px;
font-family: Avenir, ${fontFamily}, sans-serif;
border: 0;
&${antCls}-menu-horizontal {
border-bottom: none;
& > ${antCls}-menu-item, & > ${antCls}-menu-submenu {
min-width: (40px + 12px * 2);
height: ${headerHeight}px;
padding-right: 12px;
padding-left: 12px;
line-height: ${headerHeight}px;
&::after {
top: 0;
right: 12px;
bottom: auto;
left: 12px;
border-width: ${menuItemBorder}px;
}
}
& ${antCls}-menu-submenu-title ${iconCls} {
margin: 0;
}
& > ${antCls}-menu-item-selected {
a {
color: ${colorPrimary};
}
}
}
& > ${antCls}-menu-item, & > ${antCls}-menu-submenu {
text-align: center;
}
`,
popoverMenuNav: css`
${antCls}-menu-item,
${antCls}-menu-submenu {
text-align: left;
}
${antCls}-menu-item-group-title {
padding-left: 24px;
}
${antCls}-menu-item-group-list {
padding: 0 16px;
}
${antCls}-menu-item,
a {
color: #333;
}
`,
};
};
export interface NavigationProps extends SharedProps {
isMobile: boolean;
isClient: boolean;
responsive: null | 'narrow' | 'crowded';
directionText: string;
onLangChange: () => void;
onDirectionChange: () => void;
}
export default ({
isZhCN,
isClient,
isMobile,
responsive,
directionText,
onLangChange,
onDirectionChange,
}: NavigationProps) => {
const { pathname, search } = useLocation();
const [locale] = useLocale(locales);
const sidebarData = useFullSidebarData();
const blogList = sidebarData['/docs/blog']?.[0]?.children || [];
const style = useStyle();
const menuMode = isMobile ? 'inline' : 'horizontal';
const module = pathname
.split('/')
.filter((path) => path)
.slice(0, -1)
.join('/');
let activeMenuItem = module || 'home';
if (pathname.startsWith('/changelog')) {
activeMenuItem = 'docs/react';
} else if (pathname.startsWith('/docs/resources')) {
activeMenuItem = 'docs/resources';
}
let additional: MenuProps['items'];
const additionalItems: MenuProps['items'] = [
{
label: (
<a
href="https://github.com/ant-design/ant-design"
target="_blank"
rel="noopener noreferrer"
>
GitHub
</a>
),
key: 'github',
},
{
label: <FormattedMessage id="app.header.lang" />,
onClick: onLangChange,
key: 'switch-lang',
},
{
label: directionText,
onClick: onDirectionChange,
key: 'switch-direction',
},
...getEcosystemGroup(),
];
if (isMobile) {
additional = additionalItems;
} else if (responsive === 'crowded') {
additional = [
{
label: <MenuOutlined />,
key: 'additional',
children: [...additionalItems],
},
];
}
const items: MenuProps['items'] = [
{
label: (
<Link to={utils.getLocalizedPathname('/docs/spec/introduce', isZhCN, search)}>
{locale.design}
</Link>
),
key: 'docs/spec',
},
{
label: (
<Link to={utils.getLocalizedPathname('/docs/react/introduce', isZhCN, search)}>
{locale.development}
</Link>
),
key: 'docs/react',
},
{
label: (
<Link to={utils.getLocalizedPathname('/components/overview/', isZhCN, search)}>
{locale.components}
</Link>
),
key: 'components',
},
blogList.length
? {
label: (
<Link
to={utils.getLocalizedPathname(
blogList.sort((a, b) => (a.frontmatter.date > b.frontmatter.date ? -1 : 1))[0].link,
isZhCN,
search,
)}
>
{locale.blog}
</Link>
),
key: 'docs/blog',
}
: null,
{
label: (
<Link to={utils.getLocalizedPathname('/docs/resources', isZhCN, search)}>
{locale.resources}
</Link>
),
key: 'docs/resources',
},
isZhCN &&
isClient &&
window.location.host !== 'ant-design.antgroup.com' &&
window.location.host !== 'ant-design.gitee.io'
? {
label: '国内镜像',
key: 'mirror',
children: [
{
label: <a href="https://ant-design.antgroup.com"></a>,
icon: (
<img
alt="logo"
src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
width={16}
style={{ verticalAlign: 'text-bottom' }}
/>
),
key: 'antgroup',
},
{
label: <a href="https://ant-design.gitee.io">Gitee </a>,
icon: (
<img
alt="gitee"
src="https://gw.alipayobjects.com/zos/bmw-prod/9e91e124-9bab-4113-b500-301412f6b370.svg"
width={16}
style={{ verticalAlign: 'text-bottom' }}
/>
),
key: 'gitee',
},
],
}
: null,
...(additional ?? []),
];
return (
<Menu
mode={menuMode}
selectedKeys={[activeMenuItem]}
css={style.nav}
disabledOverflow
items={items}
style={{ borderRight: 0 }}
/>
);
};