12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- import React, { PureComponent } from 'react';
- import cls from 'classnames';
- import PropTypes from 'prop-types';
- import '@douyinfe/semi-foundation/timeline/timeline.scss';
- import { cssClasses, strings } from '@douyinfe/semi-foundation/timeline/constants';
- import ConfigContext from '../configProvider/context';
- import Item, { TimelineItemProps } from './item';
- export { TimelineItemProps } from './item';
- export interface Data extends TimelineItemProps {
- content: React.ReactNode;
- }
- export interface TimelineProps extends Pick<React.AriaAttributes, 'aria-label'> {
- mode?: 'left' | 'right' | 'center' | 'alternate';
- className?: string;
- style?: React.CSSProperties;
- dataSource?: Data[];
- children?: React.ReactNode | undefined;
- }
- const prefixCls = cssClasses.PREFIX;
- class Timeline extends PureComponent<TimelineProps> {
- static contextType = ConfigContext;
- static Item = Item;
- static propTypes = {
- mode: PropTypes.oneOf(strings.MODE),
- className: PropTypes.string,
- style: PropTypes.object,
- dataSource: PropTypes.array,
- };
- static defaultProps = {
- mode: 'left',
- };
- getPosCls = (ele: React.ReactElement, idx: number) => {
- const { mode } = this.props;
- if (mode === 'alternate') {
- if (ele.props.position) {
- return `${prefixCls}-item-${ele.props.position}`;
- }
- return idx % 2 === 0 ? `${prefixCls}-item-left` : `${prefixCls}-item-right`;
- }
- if (mode === 'center') {
- if (ele.props.position) {
- return `${prefixCls}-item-${ele.props.position}`;
- }
- return `${prefixCls}-item-left`;
- }
- if (mode === 'left' || mode === 'right') {
- return `${prefixCls}-item-${mode}`;
- }
- if (ele.props.position) {
- return `${prefixCls}-item-${ele.props.position}`;
- }
- return '';
- };
- addClassName = (items: React.ReactNode) => React.Children.map(items, (ele, idx) => {
- if (React.isValidElement(ele)) {
- return React.cloneElement(ele, {
- className: cls(
- ele.props.className,
- this.getPosCls(ele, idx)
- ),
- });
- }
- return ele;
- });
- render() {
- const { children, className, style, mode, dataSource } = this.props;
- const classString = cls(
- prefixCls,
- className,
- { [`${prefixCls}-${mode}`]: mode }
- );
- let childrenList;
- if (dataSource && dataSource.length) {
- const items = dataSource.map(
- (item, index) => <Item key={`timeline-item-${index}`} {...item}>{item.content}</Item>
- );
- childrenList = this.addClassName(items);
- }
- const items = childrenList || this.addClassName(children);
- return (
- <ul aria-label={this.props['aria-label']} style={style} className={classString}>
- {items}
- </ul>
- );
- }
- }
- export default Timeline;
|