Skip to content

Commit

Permalink
feat: indicator 组件 (#158)
Browse files Browse the repository at this point in the history
* feat: 添加indicator单元测试

* fix: review问题修复

Co-authored-by: lkjh3214 <13121007159@163.com>
  • Loading branch information
lkjh3214 and lkjh3214 authored Jul 18, 2022
1 parent 2145394 commit eb2be56
Show file tree
Hide file tree
Showing 9 changed files with 368 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,16 @@
"exportEmpty": true,
"desc": "选项卡切换子组件",
"author": "张晶发"
},
{
"version": "1.0.0",
"name": "Indicator",
"type": "component",
"cName": "指示器",
"desc": "显示一个任务或流程的进度,常用于开通流程。",
"sort": 16,
"show": true,
"author": "liukun"
}
]
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should match snapshot 1`] = `
<DocumentFragment>
<div
class="nut-indicator demo1"
>
<div
class="nut-indicator__dot"
/>
<div
class="nut-indicator__dot"
/>
<div
class="nut-indicator__number"
>
03
</div>
</div>
</DocumentFragment>
`;
64 changes: 64 additions & 0 deletions src/packages/indicator/__test__/indicator.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import * as React from 'react'
import { render } from '@testing-library/react'
import '@testing-library/jest-dom'

import { useState } from 'react'
import { Indicator } from '../indicator'
import Button from '@/packages/button'
import Cell from '@/packages/cell'
import Row from '@/packages/row'
import Col from '@/packages/col'

test('should match snapshot', () => {
const { asFragment } = render(
<Indicator className="demo1" size={3} current={3} />
)
expect(asFragment()).toMatchSnapshot()
})

test('should be shown when passing size and current', () => {
const { container, getByTestId } = render(
<Cell>
<Row>
<Col span="12">
<Button size="small" type="primary">
主要按钮
</Button>
</Col>
<Col span="12">
<Indicator
data-testid="indicator"
className="aa"
block
align="right"
size={6}
current={5}
/>
</Col>
</Row>
</Cell>
)
expect(getByTestId('indicator')).toHaveClass('aa')
expect(container.querySelectorAll('.nut-indicator__dot')).toHaveLength(5)
expect(container.querySelectorAll('.nut-indicator__number')).toHaveLength(1)
})

test('should be shown when passing block and align and fillZero', () => {
const IndicatorDemo = () => {
const [loading, setLoading] = useState(false)
return (
<Cell>
<Indicator block fillZero align="center" size={6} current={5} />
</Cell>
)
}

const { container } = render(<IndicatorDemo />)

const wrapper = container.querySelector('.nut-indicator')
expect(wrapper).toHaveClass('nut-indicator__align__center')
expect(wrapper).toHaveClass('nut-indicator__block')
expect(container.querySelector('.nut-indicator__number')).toHaveTextContent(
'05'
)
})
47 changes: 47 additions & 0 deletions src/packages/indicator/demo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from 'react'
import { Indicator } from './indicator'
import Cell from '@/packages/cell'
import Row from '@/packages/row'
import Col from '@/packages/col'
import Button from '@/packages/button'

const IndicatorDemo = () => {
return (
<>
<div className="demo">
<h2>基础用法</h2>
<Cell>
<Indicator className="demo1" size={3} current={3} />
</Cell>
<Cell>
<Row>
<Col span="12">
<Button size="small" type="primary">
主要按钮
</Button>
</Col>
<Col span="12">
<Indicator block align="right" size={6} current={5} />
</Col>
</Row>
</Cell>
<h2>block用法</h2>
<Cell>
<Indicator block align="center" size={6} current={5} />
</Cell>
<Cell>
<Indicator block align="left" size={6} current={1} />
</Cell>
<Cell>
<Indicator block align="right" size={6} current={5} />
</Cell>
<h2>不补0</h2>
<Cell>
<Indicator fillZero={false} size={6} current={5} />
</Cell>
</div>
</>
)
}

export default IndicatorDemo
97 changes: 97 additions & 0 deletions src/packages/indicator/doc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Indicator 指示器

### 介绍

显示一个任务或流程的进度,常用于开通流程。

### 安装

```javascript
import { Indicator } from '@nutui/nutui-react'
```
### 基础用法
:::demo
```tsx
import React from "react";
import { Indicator, Cell, Button } from '@nutui/nutui-react';

const App = () => {
return (
<Cell>
<Indicator size={3} current={3}>
</Indicator>
</Cell>
<Cell>
<Row>
<Col span="12">
<Button size="small" type="primary">
主要按钮
</Button>
</Col>
<Col span="12">
<Indicator block={true} align="right" size={6} current={5}>
</Indicator>
</Col>
</Row>
</Cell>
);
};
export default App;
```
:::
### block用法
`block`为true时,将表现为块级元素,可通过`align`,设置对齐方式
:::demo
```tsx
import React from "react";
import { Indicator, Cell } from '@nutui/nutui-react';

const App = () => {
return (
<Cell>
<Indicator block={true} align="center" size={6} current={5}>
</Indicator>
</Cell>
<Cell>
<Indicator block={true} align="left" size={6} current={1}>
</Indicator>
</Cell>
<Cell>
<Indicator block={true} align="right" size={6} current={5}>
</Indicator>
</Cell>
);
};
export default App;
```
:::
### 不补0
:::demo
```tsx
import React from "react";
import { Indicator, Cell } from '@nutui/nutui-react';

const App = () => {
return (
<Cell>
<Indicator fillZero={false} size={6} current={5}>
</Indicator>
</Cell>
);
};
export default App;
```
:::


## API

### Props

| 参数 | 说明 | 类型 | 默认值 |
|--------------|----------------------------------|--------|------------------|
| current | 当前步骤 | Number | 1 |
| size | 步骤长度 | Number | 3 |
| block | 是否启用块级布局 | Boolean | false |
| align | 对齐方式,仅在block为true时生效, 可选值 'left', 'right', 'center'| String | left |
| fillZero | 单数前面是否补0 | Boolean | true |
3 changes: 3 additions & 0 deletions src/packages/indicator/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { Indicator } from './indicator'

export default Indicator
48 changes: 48 additions & 0 deletions src/packages/indicator/indicator.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
.nut-indicator {
&__block {
display: block;
width: 100%;
}
&__align__left {
text-align: left;
}
&__align__right {
text-align: right;
}
&__align__center {
text-align: center;
}
&__dot,
&__number {
margin: 0 4px;
&:first-child {
margin-left: 0;
}
&:last-child {
margin-right: 0;
}
}
&__dot {
display: inline-block;
vertical-align: middle;
width: $indicator-dot-size;
height: $indicator-dot-size;
border-radius: 50%;
background-color: $indicator-dot-color;
}
&__number {
display: inline-block;
position: relative;
width: $indicator-size;
height: $indicator-size;
text-align: center;
font-size: $indicator-number-font-size;
line-height: $indicator-size;
color: $indicator-white;
vertical-align: middle;
border: 1px solid $indicator-white;
border-radius: 50%;
background-color: $indicator-color;
box-shadow: 0 0 1px 1px $indicator-color;
}
}
68 changes: 68 additions & 0 deletions src/packages/indicator/indicator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React, { FunctionComponent, ReactNode, useEffect } from 'react'
import classNames from 'classnames'
import bem from '@/utils/bem'

export interface IndicatorProps {
size: number
current: number
block: boolean
align: 'left' | 'right' | 'center'
fillZero: boolean
}
const defaultProps = {
size: 3,
current: 1,
block: false,
align: 'center',
fillZero: true,
} as IndicatorProps

export const Indicator: FunctionComponent<
Partial<IndicatorProps> & React.HTMLAttributes<HTMLDivElement>
> = (props) => {
const {
size,
current,
block,
align,
fillZero,
children,
className,
...rest
} = {
...defaultProps,
...props,
}
const b = bem('indicator')
const classes = classNames(
{
[`${b('block')}`]: block,
[`${b('align')}__${align}`]: block && align,
},
b('')
)
const renderEles = () => {
const childs: ReactNode[] = []
for (let item = 1; item <= size; item++) {
childs.push(
item === current ? (
<div key={item} className={b('number')}>
{fillZero && item < 10 ? `0${item}` : item}
</div>
) : (
<div key={item} className={b('dot')} />
)
)
}
return childs
}
useEffect(() => {}, [])
return (
<div className={`${classes} ${className}`} {...rest}>
{renderEles()}
</div>
)
}

Indicator.defaultProps = defaultProps
Indicator.displayName = 'NutIndicator'
10 changes: 10 additions & 0 deletions src/styles/variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,16 @@ $empty-description-color: #666666 !default;
$empty-description-font-size: 14px !default;
$empty-description-line-height: 20px !default;
$empty-description-padding: 0 40px !default;

// indicator
$indicator-color: $primary-color !default;
$indicator-dot-color: $disable-color !default;
$indicator-white: $white !default;
$indicator-size: 18px !default;
$indicator-dot-size: calc($indicator-size / 3) !default;
$indicator-border-size: $indicator-size + 2 !default;
$indicator-number-font-size: 10px !default;

// circleProgress
$circleprogress-primary-color: $primary-color !default;
$circleprogress-path-color: #e5e9f2 !default;
Expand Down

0 comments on commit eb2be56

Please sign in to comment.