Browse Source

feat: Time line data (#40424)

* feat: update timeline to data driven
pull/40613/head
黑雨 2 years ago
committed by GitHub
parent
commit
751bf40f60
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 92
      components/timeline/Timeline.tsx
  2. 1
      components/timeline/TimelineItem.tsx
  3. 92
      components/timeline/TimelineItemList.tsx
  4. 123
      components/timeline/__tests__/index.test.tsx
  5. 41
      components/timeline/demo/alternate.tsx
  6. 22
      components/timeline/demo/basic.tsx
  7. 83
      components/timeline/demo/color.tsx
  8. 26
      components/timeline/demo/custom.tsx
  9. 26
      components/timeline/demo/label.tsx
  10. 20
      components/timeline/demo/pending.tsx
  11. 27
      components/timeline/demo/right.tsx
  12. 22
      components/timeline/demo/wireframe.tsx
  13. 27
      components/timeline/index.en-US.md
  14. 27
      components/timeline/index.zh-CN.md
  15. 14
      components/timeline/useItems.tsx

92
components/timeline/Timeline.tsx

@ -1,11 +1,10 @@
import LoadingOutlined from '@ant-design/icons/LoadingOutlined';
import classNames from 'classnames';
import * as React from 'react';
import { ConfigContext } from '../config-provider';
import { cloneElement } from '../_util/reactNode';
import type { TimelineItemProps } from './TimelineItem';
import TimelineItemList from './TimelineItemList';
import TimelineItem from './TimelineItem';
import warning from '../_util/warning';
import useItems from './useItems';
// CSSINJS
import useStyle from './style';
@ -20,6 +19,7 @@ export interface TimelineProps {
style?: React.CSSProperties;
reverse?: boolean;
mode?: 'left' | 'alternate' | 'right';
items?: TimelineItemProps[];
children?: React.ReactNode;
}
@ -29,83 +29,27 @@ type CompoundedComponent = React.FC<TimelineProps> & {
const Timeline: CompoundedComponent = (props) => {
const { getPrefixCls, direction } = React.useContext(ConfigContext);
const {
prefixCls: customizePrefixCls,
pending = null,
pendingDot,
children,
className,
rootClassName,
reverse = false,
mode = '' as TimelineProps['mode'],
...restProps
} = props;
const { prefixCls: customizePrefixCls, children, items, ...restProps } = props;
const prefixCls = getPrefixCls('timeline', customizePrefixCls);
const pendingNode = typeof pending === 'boolean' ? null : pending;
// Style
const [wrapSSR, hashId] = useStyle(prefixCls);
const pendingItem = pending ? (
<TimelineItem pending={!!pending} dot={pendingDot || <LoadingOutlined />}>
{pendingNode}
</TimelineItem>
) : null;
const timeLineItems = React.Children.toArray(children);
timeLineItems.push(pendingItem!);
if (reverse) {
timeLineItems.reverse();
// =================== Warning =====================
if (process.env.NODE_ENV !== 'production') {
warning(!children, 'Timeline', '`Timeline.Item` is deprecated. Please use `items` instead.');
}
const getPositionCls = (ele: React.ReactElement<any>, idx: number) => {
if (mode === 'alternate') {
if (ele.props.position === 'right') return `${prefixCls}-item-right`;
if (ele.props.position === 'left') return `${prefixCls}-item-left`;
return idx % 2 === 0 ? `${prefixCls}-item-left` : `${prefixCls}-item-right`;
}
if (mode === 'left') return `${prefixCls}-item-left`;
if (mode === 'right') return `${prefixCls}-item-right`;
if (ele.props.position === 'right') return `${prefixCls}-item-right`;
return '';
};
// Remove falsy items
const truthyItems = timeLineItems.filter((item) => !!item);
const itemsCount = React.Children.count(truthyItems);
const lastCls = `${prefixCls}-item-last`;
const items = React.Children.map(truthyItems, (ele: React.ReactElement<any>, idx) => {
const pendingClass = idx === itemsCount - 2 ? lastCls : '';
const readyClass = idx === itemsCount - 1 ? lastCls : '';
return cloneElement(ele, {
className: classNames([
ele.props.className,
!reverse && !!pending ? pendingClass : readyClass,
getPositionCls(ele, idx),
]),
});
});
const hasLabelItem = timeLineItems.some((item: React.ReactElement<any>) => !!item?.props?.label);
// Style
const [wrapSSR, hashId] = useStyle(prefixCls);
const classString = classNames(
prefixCls,
{
[`${prefixCls}-pending`]: !!pending,
[`${prefixCls}-reverse`]: !!reverse,
[`${prefixCls}-${mode}`]: !!mode && !hasLabelItem,
[`${prefixCls}-label`]: hasLabelItem,
[`${prefixCls}-rtl`]: direction === 'rtl',
},
className,
rootClassName,
hashId,
);
const mergedItems: TimelineItemProps[] = useItems(items, children);
return wrapSSR(
<ul {...restProps} className={classString}>
{items}
</ul>,
<TimelineItemList
{...restProps}
prefixCls={prefixCls}
direction={direction}
items={mergedItems}
hashId={hashId}
/>,
);
};

1
components/timeline/TimelineItem.tsx

@ -6,6 +6,7 @@ import type { LiteralUnion } from '../_util/type';
type Color = 'blue' | 'red' | 'green' | 'gray';
export interface TimelineItemProps {
key?: React.Key;
prefixCls?: string;
className?: string;
color?: LiteralUnion<Color>;

92
components/timeline/TimelineItemList.tsx

@ -0,0 +1,92 @@
import classNames from 'classnames';
import * as React from 'react';
import LoadingOutlined from '@ant-design/icons/LoadingOutlined';
import TimelineItem from './TimelineItem';
import type { TimelineProps } from './Timeline';
import type { TimelineItemProps } from './TimelineItem';
const TimelineItemList: React.FC<TimelineProps & { hashId: string; direction?: string }> = ({
prefixCls,
className,
pending = false,
children,
items,
rootClassName,
reverse = false,
direction,
hashId,
pendingDot,
mode = '' as TimelineProps['mode'],
...restProps
}) => {
const getPositionCls = (position: string, idx: number) => {
if (mode === 'alternate') {
if (position === 'right') return `${prefixCls}-item-right`;
if (position === 'left') return `${prefixCls}-item-left`;
return idx % 2 === 0 ? `${prefixCls}-item-left` : `${prefixCls}-item-right`;
}
if (mode === 'left') return `${prefixCls}-item-left`;
if (mode === 'right') return `${prefixCls}-item-right`;
if (position === 'right') return `${prefixCls}-item-right`;
return '';
};
const mergedItems = [...(items || [])];
const pendingNode = typeof pending === 'boolean' ? null : pending;
if (pending) {
mergedItems.push({
pending: !!pending,
dot: pendingDot || <LoadingOutlined />,
children: pendingNode,
});
}
if (reverse) {
mergedItems.reverse();
}
const itemsCount = mergedItems.length;
const lastCls = `${prefixCls}-item-last`;
const itemsList = mergedItems
.filter((item: TimelineItemProps) => !!item)
.map((item: TimelineItemProps, idx: number) => {
const pendingClass = idx === itemsCount - 2 ? lastCls : '';
const readyClass = idx === itemsCount - 1 ? lastCls : '';
return (
<TimelineItem
className={classNames([
className,
!reverse && !!pending ? pendingClass : readyClass,
getPositionCls(item?.position ?? '', idx),
])}
{...item}
/* eslint-disable-next-line react/no-array-index-key */
key={item?.key || idx}
/>
);
});
const hasLabelItem = mergedItems.some((item: TimelineItemProps) => !!item?.label);
const classString = classNames(
prefixCls,
{
[`${prefixCls}-pending`]: !!pending,
[`${prefixCls}-reverse`]: !!reverse,
[`${prefixCls}-${mode}`]: !!mode && !hasLabelItem,
[`${prefixCls}-label`]: hasLabelItem,
[`${prefixCls}-rtl`]: direction === 'rtl',
},
className,
rootClassName,
hashId,
);
return (
<ul {...restProps} className={classString}>
{itemsList}
</ul>
);
};
export default TimelineItemList;

123
components/timeline/__tests__/index.test.tsx

@ -5,19 +5,22 @@ import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import { render } from '../../../tests/utils';
const { Item } = TimeLine;
const renderFactory = (
timeLineProps: TimelineProps = {},
labelItems: TimelineProps['children'] = null,
) =>
const renderFactory = (timeLineProps: TimelineProps) =>
render(
<TimeLine {...timeLineProps}>
<Item key="1">foo</Item>
<Item key="2">bar</Item>
<Item key="3">baz</Item>
{labelItems}
</TimeLine>,
<TimeLine
{...timeLineProps}
items={[
{
children: 'foo',
},
{
children: 'bar',
},
{
children: 'baz',
},
]}
/>,
);
describe('TimeLine', () => {
@ -26,8 +29,60 @@ describe('TimeLine', () => {
rtlTest(TimeLine);
rtlTest(TimeLine.Item);
describe('render TimeLine.Item', () => {
it('TimeLine.Item should correctly', () => {
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
const { container } = render(
<TimeLine reverse>
<TimeLine.Item>foo</TimeLine.Item>
<TimeLine.Item>bar</TimeLine.Item>
<TimeLine.Item>baz</TimeLine.Item>
</TimeLine>,
);
// has 3 timeline item
expect(container.querySelectorAll('li.ant-timeline-item')).toHaveLength(3);
// has only 1 timeline item is marked as the last item
expect(container.querySelectorAll('li.ant-timeline-item-last')).toHaveLength(1);
// its last item is marked as the last item
expect(container.querySelectorAll('li.ant-timeline-item')[2]).toHaveClass(
'ant-timeline-item-last',
);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: Timeline] `Timeline.Item` is deprecated. Please use `items` instead.',
);
errSpy.mockRestore();
});
it('has extra pending timeline item', () => {
const { container } = render(
<TimeLine pending={<div>pending...</div>} reverse mode="alternate">
<TimeLine.Item>foo</TimeLine.Item>
<TimeLine.Item position="right">bar</TimeLine.Item>
<TimeLine.Item position="left">baz</TimeLine.Item>
</TimeLine>,
);
expect(container.querySelectorAll('li.ant-timeline-item-pending')).toHaveLength(1);
});
it("has no pending dot if without passing a truthy 'pending' prop", () => {
const { queryByText } = render(
<TimeLine pendingDot={<i>dot</i>} reverse>
<TimeLine.Item>foo</TimeLine.Item>
<TimeLine.Item>bar</TimeLine.Item>
<TimeLine.Item position="right">baz</TimeLine.Item>
</TimeLine>,
);
expect(queryByText('dot')).toBeFalsy();
});
});
it('renders items without passing any props correctly', () => {
const { container } = renderFactory();
const { container } = renderFactory({});
// has 3 timeline item
expect(container.querySelectorAll('li.ant-timeline-item')).toHaveLength(3);
@ -132,11 +187,21 @@ describe('TimeLine', () => {
it('renders Timeline item with label correctly', () => {
const label = '2020-01-01';
const { container } = renderFactory(
{},
<Item key="1" label={label}>
foo
</Item>,
const { container } = render(
<TimeLine
items={[
{
label,
children: 'foo',
},
{
children: 'bar',
},
{
children: 'baz',
},
]}
/>,
);
expect(container.querySelectorAll('.ant-timeline-label')).toHaveLength(1);
expect(container.querySelector('.ant-timeline-item-label')).toHaveTextContent(label);
@ -148,9 +213,14 @@ describe('TimeLine', () => {
presetColors.forEach((color) => {
it(`className should have a preset color ${color}`, () => {
const { container } = render(
<TimeLine>
<Item color={color}>foo</Item>
</TimeLine>,
<TimeLine
items={[
{
color,
children: 'foo',
},
]}
/>,
);
expect(container.querySelector('.ant-timeline-item-head')).toHaveClass(
`ant-timeline-item-head-${color}`,
@ -167,9 +237,14 @@ describe('TimeLine', () => {
nonPresetColors.forEach((color) => {
it(`className should not have a non-preset color ${color}`, () => {
const { container } = render(
<TimeLine>
<Item color={color}>foo</Item>
</TimeLine>,
<TimeLine
items={[
{
color,
children: 'foo',
},
]}
/>,
);
expect(container.querySelector('.ant-timeline-item-head')).not.toHaveClass(
`ant-timeline-item-head-${color}`,

41
components/timeline/demo/alternate.tsx

@ -3,20 +3,33 @@ import { ClockCircleOutlined } from '@ant-design/icons';
import { Timeline } from 'antd';
const App: React.FC = () => (
<Timeline mode="alternate">
<Timeline.Item>Create a services site 2015-09-01</Timeline.Item>
<Timeline.Item color="green">Solve initial network problems 2015-09-01</Timeline.Item>
<Timeline.Item dot={<ClockCircleOutlined style={{ fontSize: '16px' }} />}>
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque
laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto
beatae vitae dicta sunt explicabo.
</Timeline.Item>
<Timeline.Item color="red">Network problems being solved 2015-09-01</Timeline.Item>
<Timeline.Item>Create a services site 2015-09-01</Timeline.Item>
<Timeline.Item dot={<ClockCircleOutlined style={{ fontSize: '16px' }} />}>
Technical testing 2015-09-01
</Timeline.Item>
</Timeline>
<Timeline
mode="alternate"
items={[
{
children: 'Create a services site 2015-09-01',
},
{
children: 'Solve initial network problems 2015-09-01',
color: 'green',
},
{
dot: <ClockCircleOutlined style={{ fontSize: '16px' }} />,
children: `Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.`,
},
{
color: 'red',
children: 'Network problems being solved 2015-09-01',
},
{
children: 'Create a services site 2015-09-01',
},
{
dot: <ClockCircleOutlined style={{ fontSize: '16px' }} />,
children: 'Technical testing 2015-09-01',
},
]}
/>
);
export default App;

22
components/timeline/demo/basic.tsx

@ -2,12 +2,22 @@ import React from 'react';
import { Timeline } from 'antd';
const App: React.FC = () => (
<Timeline>
<Timeline.Item>Create a services site 2015-09-01</Timeline.Item>
<Timeline.Item>Solve initial network problems 2015-09-01</Timeline.Item>
<Timeline.Item>Technical testing 2015-09-01</Timeline.Item>
<Timeline.Item>Network problems being solved 2015-09-01</Timeline.Item>
</Timeline>
<Timeline
items={[
{
children: 'Create a services site 2015-09-01',
},
{
children: 'Solve initial network problems 2015-09-01',
},
{
children: 'Technical testing 2015-09-01',
},
{
children: 'Network problems being solved 2015-09-01',
},
]}
/>
);
export default App;

83
components/timeline/demo/color.tsx

@ -3,33 +3,62 @@ import { SmileOutlined } from '@ant-design/icons';
import { Timeline } from 'antd';
const App: React.FC = () => (
<Timeline>
<Timeline.Item color="green">Create a services site 2015-09-01</Timeline.Item>
<Timeline.Item color="green">Create a services site 2015-09-01</Timeline.Item>
<Timeline.Item color="red">
<p>Solve initial network problems 1</p>
<p>Solve initial network problems 2</p>
<p>Solve initial network problems 3 2015-09-01</p>
</Timeline.Item>
<Timeline.Item>
<p>Technical testing 1</p>
<p>Technical testing 2</p>
<p>Technical testing 3 2015-09-01</p>
</Timeline.Item>
<Timeline.Item color="gray">
<p>Technical testing 1</p>
<p>Technical testing 2</p>
<p>Technical testing 3 2015-09-01</p>
</Timeline.Item>
<Timeline.Item color="gray">
<p>Technical testing 1</p>
<p>Technical testing 2</p>
<p>Technical testing 3 2015-09-01</p>
</Timeline.Item>
<Timeline.Item color="#00CCFF" dot={<SmileOutlined />}>
<p>Custom color testing</p>
</Timeline.Item>
</Timeline>
<Timeline
items={[
{
color: 'green',
children: 'Create a services site 2015-09-01',
},
{
color: 'green',
children: 'Create a services site 2015-09-01',
},
{
color: 'red',
children: (
<>
<p>Solve initial network problems 1</p>
<p>Solve initial network problems 2</p>
<p>Solve initial network problems 3 2015-09-01</p>
</>
),
},
{
children: (
<>
<p>Technical testing 1</p>
<p>Technical testing 2</p>
<p>Technical testing 3 2015-09-01</p>
</>
),
},
{
color: 'gray',
children: (
<>
<p>Technical testing 1</p>
<p>Technical testing 2</p>
<p>Technical testing 3 2015-09-01</p>
</>
),
},
{
color: 'gray',
children: (
<>
<p>Technical testing 1</p>
<p>Technical testing 2</p>
<p>Technical testing 3 2015-09-01</p>
</>
),
},
{
color: '#00CCFF',
dot: <SmileOutlined />,
children: <p>Custom color testing</p>,
},
]}
/>
);
export default App;

26
components/timeline/demo/custom.tsx

@ -3,14 +3,24 @@ import { ClockCircleOutlined } from '@ant-design/icons';
import { Timeline } from 'antd';
const App: React.FC = () => (
<Timeline>
<Timeline.Item>Create a services site 2015-09-01</Timeline.Item>
<Timeline.Item>Solve initial network problems 2015-09-01</Timeline.Item>
<Timeline.Item dot={<ClockCircleOutlined className="timeline-clock-icon" />} color="red">
Technical testing 2015-09-01
</Timeline.Item>
<Timeline.Item>Network problems being solved 2015-09-01</Timeline.Item>
</Timeline>
<Timeline
items={[
{
children: 'Create a services site 2015-09-01',
},
{
children: 'Solve initial network problems 2015-09-01',
},
{
dot: <ClockCircleOutlined className="timeline-clock-icon" />,
color: 'red',
children: 'Technical testing 2015-09-01',
},
{
children: 'Network problems being solved 2015-09-01',
},
]}
/>
);
export default App;

26
components/timeline/demo/label.tsx

@ -22,12 +22,26 @@ const App: React.FC = () => {
<Radio value="right">Right</Radio>
<Radio value="alternate">Alternate</Radio>
</Radio.Group>
<Timeline mode={mode}>
<Timeline.Item label="2015-09-01">Create a services</Timeline.Item>
<Timeline.Item label="2015-09-01 09:12:11">Solve initial network problems</Timeline.Item>
<Timeline.Item>Technical testing</Timeline.Item>
<Timeline.Item label="2015-09-01 09:12:11">Network problems being solved</Timeline.Item>
</Timeline>
<Timeline
mode={mode}
items={[
{
label: '2015-09-01',
children: 'Create a services',
},
{
label: '2015-09-01 09:12:11',
children: 'Solve initial network problems',
},
{
children: 'Technical testing',
},
{
label: '2015-09-01 09:12:11',
children: 'Network problems being solved',
},
]}
/>
</>
);
};

20
components/timeline/demo/pending.tsx

@ -10,11 +10,21 @@ const App: React.FC = () => {
return (
<div>
<Timeline pending="Recording..." reverse={reverse}>
<Timeline.Item>Create a services site 2015-09-01</Timeline.Item>
<Timeline.Item>Solve initial network problems 2015-09-01</Timeline.Item>
<Timeline.Item>Technical testing 2015-09-01</Timeline.Item>
</Timeline>
<Timeline
pending="Recording..."
reverse={reverse}
items={[
{
children: 'Create a services site 2015-09-01',
},
{
children: 'Solve initial network problems 2015-09-01',
},
{
children: 'Technical testing 2015-09-01',
},
]}
/>
<Button type="primary" style={{ marginTop: 16 }} onClick={handleClick}>
Toggle Reverse
</Button>

27
components/timeline/demo/right.tsx

@ -3,14 +3,25 @@ import { ClockCircleOutlined } from '@ant-design/icons';
import { Timeline } from 'antd';
const App: React.FC = () => (
<Timeline mode="right">
<Timeline.Item>Create a services site 2015-09-01</Timeline.Item>
<Timeline.Item>Solve initial network problems 2015-09-01</Timeline.Item>
<Timeline.Item dot={<ClockCircleOutlined style={{ fontSize: '16px' }} />} color="red">
Technical testing 2015-09-01
</Timeline.Item>
<Timeline.Item>Network problems being solved 2015-09-01</Timeline.Item>
</Timeline>
<Timeline
mode="right"
items={[
{
children: 'Create a services site 2015-09-01',
},
{
children: 'Solve initial network problems 2015-09-01',
},
{
dot: <ClockCircleOutlined style={{ fontSize: '16px' }} />,
color: 'red',
children: 'Technical testing 2015-09-01',
},
{
children: 'Network problems being solved 2015-09-01',
},
]}
/>
);
export default App;

22
components/timeline/demo/wireframe.tsx

@ -3,12 +3,22 @@ import { ConfigProvider, Timeline } from 'antd';
const App: React.FC = () => (
<ConfigProvider theme={{ token: { wireframe: true } }}>
<Timeline>
<Timeline.Item>Create a services site 2015-09-01</Timeline.Item>
<Timeline.Item>Solve initial network problems 2015-09-01</Timeline.Item>
<Timeline.Item>Technical testing 2015-09-01</Timeline.Item>
<Timeline.Item>Network problems being solved 2015-09-01</Timeline.Item>
</Timeline>
<Timeline
items={[
{
children: 'Create a services site 2015-09-01',
},
{
children: 'Solve initial network problems 2015-09-01',
},
{
children: 'Technical testing 2015-09-01',
},
{
children: 'Network problems being solved 2015-09-01',
},
]}
/>
</ConfigProvider>
);

27
components/timeline/index.en-US.md

@ -26,29 +26,37 @@ Vertical display timeline.
<code src="./demo/label.tsx">Label</code>
<code src="./demo/wireframe.tsx" debug>Wireframe</code>
## API
```__react
import Alert from '../alert';
ReactDOM.render(<Alert message="After version 5.3.0, we provide a simpler usage <Timeline items={[...]} /> with better performance and potential of writing simpler code style in your applications. Meanwhile, we deprecated the old usage in browser console, we will remove it in antd 6.0." />, mountNode);
```
```jsx
<Timeline>
<Timeline.Item>step1 2015-09-01</Timeline.Item>
<Timeline.Item>step2 2015-09-01</Timeline.Item>
<Timeline.Item>step3 2015-09-01</Timeline.Item>
<Timeline.Item>step4 2015-09-01</Timeline.Item>
</Timeline>
// works when >=5.3.0, recommended ✅
const items = [{ children: 'sample', label: 'sample' }];
return <Timeline items={items} />;
// works when <5.3.0, deprecated when >=5.3.0 🙅🏻‍♀️
<Timeline onChange={onChange}>
<Timeline.Item>Sample</Timeline.Item>
</Timeline>;
```
## API
### Timeline
Timeline
| Property | Description | Type | Default |
| --- | --- | --- | --- |
| --- | --- | --- | --- | --- |
| mode | By sending `alternate` the timeline will distribute the nodes to the left and right | `left` \| `alternate` \| `right` | - |
| pending | Set the last ghost node's existence or its content | boolean \| ReactNode | false |
| pendingDot | Set the dot of the last ghost node when pending is true | ReactNode | &lt;LoadingOutlined /> |
| reverse | Whether reverse nodes or not | boolean | false |
| items | 选项配置 | [Items](#Items) | [] | 5.3.0 |
### Timeline.Item
### Items
Node of timeline
@ -57,4 +65,5 @@ Node of timeline
| color | Set the circle's color to `blue`, `red`, `green`, `gray` or other custom colors | string | `blue` |
| dot | Customize timeline dot | ReactNode | - |
| label | Set the label | ReactNode | - |
| children | Set the content | ReactNode | - |
| position | Customize node position | `left` \| `right` | - |

27
components/timeline/index.zh-CN.md

@ -27,29 +27,37 @@ demo:
<code src="./demo/label.tsx">标签</code>
<code src="./demo/wireframe.tsx" debug>线框风格</code>
## API
```__react
import Alert from '../alert';
ReactDOM.render(<Alert message="After version 5.3.0, we provide a simpler usage <Timeline items={[...]} /> with better performance and potential of writing simpler code style in your applications. Meanwhile, we deprecated the old usage in browser console, we will remove it in antd 6.0." />, mountNode);
```
```jsx
<Timeline>
<Timeline.Item>创建服务现场 2015-09-01</Timeline.Item>
<Timeline.Item>初步排除网络异常 2015-09-01</Timeline.Item>
<Timeline.Item>技术测试异常 2015-09-01</Timeline.Item>
<Timeline.Item>网络异常正在修复 2015-09-01</Timeline.Item>
</Timeline>
// >=5.3.0 可用,推荐的写法 ✅
const items = [{ children: 'sample', label: 'sample' }];
return <Timeline items={items} />;
// <5.3.0 可用>=5.3.0 时不推荐 🙅🏻‍♀️
<Timeline onChange={onChange}>
<Timeline.Item>Sample</Timeline.Item>
</Timeline>;
```
## API
### Timeline
时间轴。
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| --- | --- | --- | --- | --- |
| mode | 通过设置 `mode` 可以改变时间轴和内容的相对位置 | `left` \| `alternate` \| `right` | - |
| pending | 指定最后一个幽灵节点是否存在或内容 | boolean \| ReactNode | false |
| pendingDot | 当最后一个幽灵节点存在時,指定其时间图点 | ReactNode | &lt;LoadingOutlined /> |
| reverse | 节点排序 | boolean | false |
| items | 选项配置 | [Items](#Items) | [] | 5.3.0 |
### Timeline.Item
### Items
时间轴的每一个节点。
@ -58,4 +66,5 @@ demo:
| color | 指定圆圈颜色 `blue`、`red`、`green`、`gray`,或自定义的色值 | string | `blue` |
| dot | 自定义时间轴点 | ReactNode | - |
| label | 设置标签 | ReactNode | - |
| children | 设置内容 | ReactNode | - |
| position | 自定义节点位置 | `left` \| `right` | - |

14
components/timeline/useItems.tsx

@ -0,0 +1,14 @@
import type * as React from 'react';
import toArray from 'rc-util/lib/Children/toArray';
import type { TimelineItemProps } from './TimelineItem';
function useItems(items?: TimelineItemProps[], children?: React.ReactNode): TimelineItemProps[] {
if (items && Array.isArray(items)) return items;
return toArray(children).map((ele: React.ReactElement<any>) => ({
children: ele?.props?.children ?? '',
...ele.props,
}));
}
export default useItems;
Loading…
Cancel
Save