ant-design/components/breadcrumb/Breadcrumb.tsx

114 lines
3.1 KiB
TypeScript
Raw Normal View History

import * as React from 'react';
2018-08-07 21:07:52 +08:00
import * as PropTypes from 'prop-types';
2016-07-14 13:29:50 +08:00
import { cloneElement } from 'react';
import warning from '../_util/warning';
2016-03-31 17:46:35 +08:00
import BreadcrumbItem from './BreadcrumbItem';
import classNames from 'classnames';
2016-03-31 17:46:35 +08:00
2017-11-22 11:10:33 +08:00
export interface Route {
path: string;
breadcrumbName: string;
}
export interface BreadcrumbProps {
prefixCls?: string;
2017-11-22 11:10:33 +08:00
routes?: Route[];
params?: any;
separator?: React.ReactNode;
itemRender?: (route: any, params: any, routes: Array<any>, paths: Array<string>) => React.ReactNode;
style?: React.CSSProperties;
className?: string;
}
2017-11-22 11:10:33 +08:00
function getBreadcrumbName(route: Route, params: any) {
if (!route.breadcrumbName) {
2016-06-10 21:12:52 +08:00
return null;
}
2016-06-11 17:05:19 +08:00
const paramsKeys = Object.keys(params).join('|');
const name = route.breadcrumbName.replace(
2016-06-11 17:05:19 +08:00
new RegExp(`:(${paramsKeys})`, 'g'),
(replacement, key) => params[key] || replacement,
);
return name;
2016-07-14 13:29:50 +08:00
}
2017-11-22 11:10:33 +08:00
function defaultItemRender(route: Route, params: any, routes: Route[], paths: string[]) {
2016-10-24 12:04:26 +08:00
const isLastItem = routes.indexOf(route) === routes.length - 1;
const name = getBreadcrumbName(route, params);
return isLastItem
? <span>{name}</span>
: <a href={`#/${paths.join('/')}`}>{name}</a>;
}
2016-07-14 13:29:50 +08:00
export default class Breadcrumb extends React.Component<BreadcrumbProps, any> {
static Item: typeof BreadcrumbItem;
2016-07-14 13:29:50 +08:00
2016-03-31 17:46:35 +08:00
static defaultProps = {
prefixCls: 'ant-breadcrumb',
separator: '/',
2016-07-13 11:14:24 +08:00
};
2016-03-31 17:46:35 +08:00
static propTypes = {
prefixCls: PropTypes.string,
separator: PropTypes.node,
routes: PropTypes.array,
params: PropTypes.object,
linkRender: PropTypes.func,
nameRender: PropTypes.func,
2016-07-13 11:14:24 +08:00
};
2016-03-31 17:46:35 +08:00
componentDidMount() {
const props = this.props;
warning(
!('linkRender' in props || 'nameRender' in props),
'`linkRender` and `nameRender` are removed, please use `itemRender` instead, ' +
'see: https://u.ant.design/item-render.',
);
}
2016-03-31 17:46:35 +08:00
render() {
let crumbs;
const {
separator, prefixCls, style, className, routes, params = {},
children, itemRender = defaultItemRender,
} = this.props;
2016-03-31 17:46:35 +08:00
if (routes && routes.length > 0) {
2016-10-24 12:04:26 +08:00
const paths: string[] = [];
2016-10-20 19:19:16 +08:00
crumbs = routes.map((route) => {
2016-04-11 11:31:35 +08:00
route.path = route.path || '';
2016-10-24 12:04:26 +08:00
let path: string = route.path.replace(/^\//, '');
2016-03-31 17:46:35 +08:00
Object.keys(params).forEach(key => {
path = path.replace(`:${key}`, params[key]);
});
if (path) {
paths.push(path);
}
return (
<BreadcrumbItem separator={separator} key={route.breadcrumbName || path}>
{itemRender(route, params, routes, paths)}
</BreadcrumbItem>
);
2016-03-31 17:46:35 +08:00
});
2016-10-24 12:04:26 +08:00
} else if (children) {
2016-07-14 13:29:50 +08:00
crumbs = React.Children.map(children, (element: any, index) => {
if (!element) {
return element;
}
warning(
element.type && element.type.__ANT_BREADCRUMB_ITEM,
'Breadcrumb only accepts Breadcrumb.Item as it\'s children',
);
2016-03-31 17:46:35 +08:00
return cloneElement(element, {
separator,
key: index,
});
});
}
return (
<div className={classNames(className, prefixCls)} style={style}>
2016-03-31 17:46:35 +08:00
{crumbs}
</div>
);
}
}