mirror of
https://github.com/ant-design/ant-design.git
synced 2024-12-15 08:59:15 +08:00
afedb4127f
* patch route * use data for promise * rename Article file * Article in TS * clean up * use collect * adjust css * card it * listing * res * hiring * add footer * english it * rm others * fix lint * fix navigation * add dropdown button * Header with TS * split input & logo * navigation out * use flex * flex everything * stretch * hide search when narrow * init category * global rules * more cat * pages * level 2 width * level 3 * level 4 * skip before ready * clean up * unqiue shadow variable * update eslintignore * update ignore * fix ssr * fix location param * replace images * shake more * fix top of navigation * remove home * reorder nav & adjust padding style * narrow res style * Update research-form-page.zh-CN.md (#21426) Co-authored-by: Golevka <huangsamfisher@163.com> * rm skip * narrow merge in * reset p style * update svg * fix lint * update ignore * update lint ignore * Update research-result-page.zh-CN.md (#21432) Co-authored-by: mihaideyu <zxy1010414746@163.com> * Update research-result-page.zh-CN.md * Update research-workbench.zh-CN.md (#21438) Co-authored-by: yingxirz <inseeing@gmail.com> * Update research-workbench.zh-CN.md * Update research-list-page.zh-CN.md (#21441) Co-authored-by: yingxirz <inseeing@gmail.com> * Update research-list-page.zh-CN.md * padding use 40px * add responsive of ref * fix p margin * Update research-workbench.zh-CN.md * Update buttons.md (#21456) Co-authored-by: yingxirz <inseeing@gmail.com> * Update resources.en-US.md (#21457) * Update research-navigation.zh-CN.md (#21453) * Update research-navigation.zh-CN.md * Update research-navigation.zh-CN.md * Update research-navigation.zh-CN.md * Update research-empty.zh-CN.md (#21451) * Update research-empty.zh-CN.md * Update research-empty.zh-CN.md * Update research-empty.zh-CN.md * Update research-empty.zh-CN.md Co-authored-by: 二货机器人 <smith3816@gmail.com> * Update research-exception-page.zh-CN.md (#21452) * Update research-exception-page.zh-CN.md * Update research-exception-page.zh-CN.md * Update research-message-and-feedback.zh-CN.md (#21463) * Update research-message-and-feedback.zh-CN.md (#21467) * Update research-message-and-feedback.zh-CN.md * Update research-message-and-feedback.zh-CN.md * Update research-message-and-feedback.zh-CN.md * Update research-message-and-feedback.zh-CN.md * replace background * fix lines margin * home padding * patch minTilda doc * Update resources.zh-CN.md (#21503) * clean up * Update research-workbench.zh-CN.md (#21512) Co-authored-by: yingxirz <inseeing@gmail.com> * Update research-overview.zh-CN.md (#21513) Co-authored-by: yingxirz <inseeing@gmail.com> * Update research-result-page.zh-CN.md (#21514) Co-authored-by: mihaideyu <zxy1010414746@163.com> * Update research-list-page.zh-CN.md (#21515) Co-authored-by: yingxirz <inseeing@gmail.com> * fix doc * Update research-message-and-feedback.zh-CN.md (#21516) * adjust home nav width * Update research-message-and-feedback.zh-CN.md (#21535) * Update research-form-page.zh-CN.md (#21554) Co-authored-by: Golevka <huangsamfisher@163.com> * patch file * clean up * update shadow.zh-CN update shadow.zh-CN * add shadow table * Update visual.zh-CN.md (#21577) Co-authored-by: shuwenliu0116 <33922479+shuwenliu0116@users.noreply.github.com> * Update docs/spec/shadow.zh-CN.md Co-Authored-By: 偏右 <afc163@gmail.com> * Update docs/spec/shadow.zh-CN.md Co-Authored-By: 偏右 <afc163@gmail.com> * Update docs/spec/shadow.zh-CN.md Co-Authored-By: 偏右 <afc163@gmail.com> * Update docs/spec/shadow.zh-CN.md Co-Authored-By: 偏右 <afc163@gmail.com> * Update docs/spec/shadow.zh-CN.md Co-Authored-By: 偏右 <afc163@gmail.com> * patch docs * fix doc * rm page suffix * fix style * mobile it * Update resources.en-US.md (#21561) * chart res * add qr code * adjust qr * Update visual.zh-CN.md (#21603) Co-authored-by: shuwenliu0116 <33922479+shuwenliu0116@users.noreply.github.com> * fix site qr * mobile height of it * book update * 3.x site link * isMobile is new cnotext * Update research-form.zh-CN.md (#21604) Co-authored-by: Golevka <huangsamfisher@163.com> * adjust form doc * mobile use link * adjust order * flush * fix ts * Update research-navigation.zh-CN.md (#21606) * Update research-navigation.zh-CN.md (#21609) * rm useless lines * add mobile icon * Update research-exception.zh-CN.md (#21612) * Update research-empty.zh-CN.md (#21610) * Update research-workbench.zh-CN.md * Update visual.zh-CN.md * adjust mobile icon * Update research-message-and-feedback.zh-CN.md (#21613) * Update research-list.zh-CN.md (#21617) Co-authored-by: yingxirz <inseeing@gmail.com> * Update research-workbench.zh-CN.md (#21618) Co-authored-by: yingxirz <inseeing@gmail.com> * Update visual.zh-CN.md (#21619) Co-authored-by: shuwenliu0116 <33922479+shuwenliu0116@users.noreply.github.com> * Update research-result.zh-CN.md (#21620) Co-authored-by: mihaideyu <zxy1010414746@163.com> * Update research-form.zh-CN.md (#21615) * Update research-message-and-feedback.zh-CN.md (#21616) * Update research-list.zh-CN.md (#21621) Co-authored-by: yingxirz <inseeing@gmail.com> * Update research-result.zh-CN.md (#21624) Co-authored-by: mihaideyu <zxy1010414746@163.com> * update ref color * update zip file * fix mobile icon * rm skip dark * fix cat * update zip link * update zip link Co-authored-by: Golevka <huangsamfisher@163.com> Co-authored-by: mihaideyu <zxy1010414746@163.com> Co-authored-by: yingxirz <inseeing@gmail.com> Co-authored-by: 偏右 <afc163@gmail.com> Co-authored-by: myeunhyuk <39618466+myeunhyuk@users.noreply.github.com> Co-authored-by: minTilda <31951290+minTilda@users.noreply.github.com> Co-authored-by: ziyuan-174774 <61226089+ziyuan-174774@users.noreply.github.com> Co-authored-by: 竹尔 <54707870+AntDesigners@users.noreply.github.com> Co-authored-by: shuwenliu0116 <33922479+shuwenliu0116@users.noreply.github.com>
410 lines
13 KiB
JavaScript
410 lines
13 KiB
JavaScript
import React, { Component } from 'react';
|
|
import PropTypes from 'prop-types';
|
|
import { Link } from 'bisheng/router';
|
|
import { Row, Col, Menu, Affix, Tooltip, Avatar } from 'antd';
|
|
import { injectIntl } from 'react-intl';
|
|
import { LeftOutlined, RightOutlined, ExportOutlined } from '@ant-design/icons';
|
|
import ContributorsList from '@qixian.cs/github-contributors-list';
|
|
import classNames from 'classnames';
|
|
import get from 'lodash/get';
|
|
import MobileMenu from 'rc-drawer';
|
|
|
|
import { DarkIcon, DefaultIcon } from './ThemeIcon';
|
|
import Article from './Article';
|
|
import PrevAndNext from './PrevAndNext';
|
|
import Footer from '../Layout/Footer';
|
|
import SiteContext from '../Layout/SiteContext';
|
|
import ComponentDoc from './ComponentDoc';
|
|
import * as utils from '../utils';
|
|
|
|
const { SubMenu } = Menu;
|
|
|
|
function getModuleData(props) {
|
|
const { pathname } = props.location;
|
|
const moduleName = /^\/?components/.test(pathname)
|
|
? 'components'
|
|
: pathname
|
|
.split('/')
|
|
.filter(item => item)
|
|
.slice(0, 2)
|
|
.join('/');
|
|
const excludedSuffix = utils.isZhCN(props.location.pathname) ? 'en-US.md' : 'zh-CN.md';
|
|
let data;
|
|
switch (moduleName) {
|
|
case 'docs/react':
|
|
case 'changelog':
|
|
case 'changelog-cn':
|
|
data = [...props.picked['docs/react'], ...props.picked.changelog];
|
|
break;
|
|
default:
|
|
data = props.picked[moduleName];
|
|
}
|
|
return data.filter(({ meta }) => !meta.filename.endsWith(excludedSuffix));
|
|
}
|
|
|
|
function fileNameToPath(filename) {
|
|
const snippets = filename.replace(/(\/index)?((\.zh-CN)|(\.en-US))?\.md$/i, '').split('/');
|
|
return snippets[snippets.length - 1];
|
|
}
|
|
|
|
const getSideBarOpenKeys = nextProps => {
|
|
const { themeConfig } = nextProps;
|
|
const { pathname } = nextProps.location;
|
|
const locale = utils.isZhCN(pathname) ? 'zh-CN' : 'en-US';
|
|
const moduleData = getModuleData(nextProps);
|
|
const shouldOpenKeys = utils
|
|
.getMenuItems(moduleData, locale, themeConfig.categoryOrder, themeConfig.typeOrder)
|
|
.map(m => (m.title && m.title[locale]) || m.title);
|
|
return shouldOpenKeys;
|
|
};
|
|
|
|
class MainContent extends Component {
|
|
static contextTypes = {
|
|
theme: PropTypes.oneOf(['default', 'dark']),
|
|
setTheme: PropTypes.func,
|
|
setIframeTheme: PropTypes.func,
|
|
};
|
|
|
|
state = {
|
|
openKeys: undefined,
|
|
};
|
|
|
|
componentDidMount() {
|
|
this.componentDidUpdate();
|
|
window.addEventListener('load', this.handleInitialHashOnLoad);
|
|
}
|
|
|
|
static getDerivedStateFromProps(props, state) {
|
|
if (!state.openKeys) {
|
|
return {
|
|
...state,
|
|
openKeys: getSideBarOpenKeys(props),
|
|
};
|
|
}
|
|
return null;
|
|
}
|
|
|
|
componentDidUpdate(prevProps) {
|
|
const { location } = this.props;
|
|
const { location: prevLocation = {} } = prevProps || {};
|
|
if (!prevProps || prevLocation.pathname !== location.pathname) {
|
|
this.bindScroller();
|
|
}
|
|
if (!window.location.hash && prevLocation.pathname !== location.pathname) {
|
|
window.scrollTo(0, 0);
|
|
}
|
|
// when subMenu not equal
|
|
if (get(this.props, 'route.path') !== get(prevProps, 'route.path')) {
|
|
// reset menu OpenKeys
|
|
this.handleMenuOpenChange();
|
|
}
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
this.scroller.destroy();
|
|
window.removeEventListener('load', this.handleInitialHashOnLoad);
|
|
}
|
|
|
|
getMenuItems(footerNavIcons = {}) {
|
|
const {
|
|
themeConfig,
|
|
intl: { locale },
|
|
} = this.props;
|
|
const moduleData = getModuleData(this.props);
|
|
const menuItems = utils.getMenuItems(
|
|
moduleData,
|
|
locale,
|
|
themeConfig.categoryOrder,
|
|
themeConfig.typeOrder,
|
|
);
|
|
return menuItems.map(menuItem => {
|
|
if (menuItem.type === 'type') {
|
|
return (
|
|
<Menu.ItemGroup title={menuItem.title} key={menuItem.title}>
|
|
{menuItem.children
|
|
.sort((a, b) => a.title.charCodeAt(0) - b.title.charCodeAt(0))
|
|
.map(leaf => this.generateMenuItem(false, leaf, footerNavIcons))}
|
|
</Menu.ItemGroup>
|
|
);
|
|
}
|
|
if (menuItem.children) {
|
|
return (
|
|
<SubMenu title={menuItem.title} key={menuItem.title}>
|
|
{menuItem.children.map(child => {
|
|
if (child.type === 'type') {
|
|
return (
|
|
<Menu.ItemGroup title={child.title} key={child.title}>
|
|
{child.children.map(leaf => this.generateMenuItem(false, leaf, footerNavIcons))}
|
|
</Menu.ItemGroup>
|
|
);
|
|
}
|
|
return this.generateMenuItem(false, child, footerNavIcons);
|
|
})}
|
|
</SubMenu>
|
|
);
|
|
}
|
|
return this.generateMenuItem(true, menuItem, footerNavIcons);
|
|
});
|
|
}
|
|
|
|
getFooterNav(menuItems, activeMenuItem) {
|
|
const menuItemsList = this.flattenMenu(menuItems);
|
|
let activeMenuItemIndex = -1;
|
|
menuItemsList.forEach((menuItem, i) => {
|
|
if (menuItem && menuItem.key === activeMenuItem) {
|
|
activeMenuItemIndex = i;
|
|
}
|
|
});
|
|
const prev = menuItemsList[activeMenuItemIndex - 1];
|
|
const next = menuItemsList[activeMenuItemIndex + 1];
|
|
return { prev, next };
|
|
}
|
|
|
|
getActiveMenuItem() {
|
|
const {
|
|
params: { children },
|
|
location,
|
|
} = this.props;
|
|
return (
|
|
(children && children.replace('-cn', '')) || location.pathname.replace(/(^\/|-cn$)/g, '')
|
|
);
|
|
}
|
|
|
|
handleMenuOpenChange = openKeys => {
|
|
this.setState({ openKeys });
|
|
};
|
|
|
|
handleInitialHashOnLoad = () => {
|
|
setTimeout(() => {
|
|
if (!window.location.hash) {
|
|
return;
|
|
}
|
|
const element = document.getElementById(
|
|
decodeURIComponent(window.location.hash.replace('#', '')),
|
|
);
|
|
if (element && document.documentElement.scrollTop === 0) {
|
|
element.scrollIntoView();
|
|
}
|
|
}, 0);
|
|
};
|
|
|
|
bindScroller() {
|
|
if (this.scroller) {
|
|
this.scroller.destroy();
|
|
}
|
|
if (!document.querySelector('.markdown > h2, .code-box')) {
|
|
return;
|
|
}
|
|
require('intersection-observer'); // eslint-disable-line
|
|
const scrollama = require('scrollama'); // eslint-disable-line
|
|
this.scroller = scrollama();
|
|
this.scroller
|
|
.setup({
|
|
step: '.markdown > h2, .code-box', // required
|
|
offset: 0,
|
|
})
|
|
.onStepEnter(({ element }) => {
|
|
[].forEach.call(document.querySelectorAll('.toc-affix li a'), node => {
|
|
node.className = ''; // eslint-disable-line
|
|
});
|
|
const currentNode = document.querySelectorAll(`.toc-affix li a[href="#${element.id}"]`)[0];
|
|
if (currentNode) {
|
|
currentNode.className = 'current';
|
|
}
|
|
});
|
|
}
|
|
|
|
generateMenuItem(isTop, item, { before = null, after = null }) {
|
|
const {
|
|
intl: { locale },
|
|
} = this.props;
|
|
const key = fileNameToPath(item.filename);
|
|
if (!item.title) {
|
|
return null;
|
|
}
|
|
const title = item.title[locale] || item.title;
|
|
const text = isTop
|
|
? title
|
|
: [
|
|
<span key="english">{title}</span>,
|
|
<span className="chinese" key="chinese">
|
|
{item.subtitle}
|
|
</span>,
|
|
];
|
|
const { disabled } = item;
|
|
const url = item.filename.replace(/(\/index)?((\.zh-CN)|(\.en-US))?\.md$/i, '').toLowerCase();
|
|
const child = !item.link ? (
|
|
<Link
|
|
to={utils.getLocalizedPathname(
|
|
/^components/.test(url) ? `${url}/` : url,
|
|
locale === 'zh-CN',
|
|
)}
|
|
disabled={disabled}
|
|
>
|
|
{before}
|
|
{text}
|
|
{after}
|
|
</Link>
|
|
) : (
|
|
<a
|
|
href={item.link}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
disabled={disabled}
|
|
className="menu-item-link-outside"
|
|
>
|
|
{before}
|
|
{text} <ExportOutlined />
|
|
{after}
|
|
</a>
|
|
);
|
|
|
|
return (
|
|
<Menu.Item key={key.toLowerCase()} disabled={disabled}>
|
|
{child}
|
|
</Menu.Item>
|
|
);
|
|
}
|
|
|
|
flattenMenu(menu) {
|
|
if (!menu) {
|
|
return null;
|
|
}
|
|
if (menu.type && menu.type.isMenuItem) {
|
|
return menu;
|
|
}
|
|
if (Array.isArray(menu)) {
|
|
return menu.reduce((acc, item) => acc.concat(this.flattenMenu(item)), []);
|
|
}
|
|
return this.flattenMenu((menu.props && menu.props.children) || menu.children);
|
|
}
|
|
|
|
changeTheme = () => {
|
|
const { theme, setTheme } = this.context;
|
|
const nextTheme = theme !== 'dark' ? 'dark' : 'default';
|
|
setTheme(nextTheme);
|
|
};
|
|
|
|
render() {
|
|
return (
|
|
<SiteContext.Consumer>
|
|
{({ isMobile }) => {
|
|
const { theme, setIframeTheme } = this.context;
|
|
const { openKeys } = this.state;
|
|
const {
|
|
localizedPageData,
|
|
demos,
|
|
intl: { formatMessage },
|
|
} = this.props;
|
|
const { meta } = localizedPageData;
|
|
const activeMenuItem = this.getActiveMenuItem();
|
|
const menuItems = this.getMenuItems();
|
|
const menuItemsForFooterNav = this.getMenuItems({
|
|
before: <LeftOutlined className="footer-nav-icon-before" />,
|
|
after: <RightOutlined className="footer-nav-icon-after" />,
|
|
});
|
|
const { prev, next } = this.getFooterNav(menuItemsForFooterNav, activeMenuItem);
|
|
const mainContainerClass = classNames('main-container', {
|
|
'main-container-component': !!demos,
|
|
});
|
|
const menuChild = (
|
|
<Menu
|
|
inlineIndent={30}
|
|
className="aside-container menu-site"
|
|
mode="inline"
|
|
openKeys={openKeys}
|
|
selectedKeys={[activeMenuItem]}
|
|
onOpenChange={this.handleMenuOpenChange}
|
|
>
|
|
{menuItems}
|
|
</Menu>
|
|
);
|
|
const componentPage = /^\/?components/.test(this.props.location.pathname);
|
|
|
|
return (
|
|
<div className="main-wrapper">
|
|
<Row>
|
|
{isMobile ? (
|
|
<MobileMenu key="Mobile-menu" wrapperClassName="drawer-wrapper">
|
|
{menuChild}
|
|
</MobileMenu>
|
|
) : (
|
|
<Col xxl={4} xl={5} lg={6} md={6} sm={24} xs={24} className="main-menu">
|
|
<Affix>
|
|
<section className="main-menu-inner">{menuChild}</section>
|
|
</Affix>
|
|
</Col>
|
|
)}
|
|
<Col xxl={20} xl={19} lg={18} md={18} sm={24} xs={24}>
|
|
<section className={mainContainerClass}>
|
|
{demos ? (
|
|
<ComponentDoc
|
|
{...this.props}
|
|
doc={localizedPageData}
|
|
demos={demos}
|
|
theme={theme}
|
|
setIframeTheme={setIframeTheme}
|
|
/>
|
|
) : (
|
|
<Article {...this.props} content={localizedPageData} />
|
|
)}
|
|
<ContributorsList
|
|
className="contributors-list"
|
|
fileName={meta.filename}
|
|
renderItem={(item, loading) =>
|
|
loading ? (
|
|
<Avatar style={{ opacity: 0.3 }} />
|
|
) : (
|
|
<Tooltip
|
|
title={`${formatMessage({ id: 'app.content.contributors' })}: ${
|
|
item.username
|
|
}`}
|
|
key={item.username}
|
|
>
|
|
<a
|
|
href={`https://github.com/${item.username}`}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
>
|
|
<Avatar src={item.url}>{item.username}</Avatar>
|
|
</a>
|
|
</Tooltip>
|
|
)
|
|
}
|
|
repo="ant-design"
|
|
owner="ant-design"
|
|
/>
|
|
</section>
|
|
{componentPage && (
|
|
<div className="fixed-widgets">
|
|
<Tooltip
|
|
getPopupContainer={node => node.parentNode}
|
|
title={formatMessage({ id: `app.theme.switch.${theme}` })}
|
|
overlayClassName="fixed-widgets-tooltip"
|
|
>
|
|
<Avatar
|
|
className={classNames(
|
|
'fixed-widgets-avatar',
|
|
`fixed-widgets-avatar-${theme}`,
|
|
)}
|
|
size={44}
|
|
onClick={this.changeTheme}
|
|
icon={theme === 'dark' ? <DarkIcon /> : <DefaultIcon />}
|
|
/>
|
|
</Tooltip>
|
|
</div>
|
|
)}
|
|
<PrevAndNext prev={prev} next={next} />
|
|
<Footer />
|
|
</Col>
|
|
</Row>
|
|
</div>
|
|
);
|
|
}}
|
|
</SiteContext.Consumer>
|
|
);
|
|
}
|
|
}
|
|
|
|
export default injectIntl(MainContent);
|