Skip to content

Commit

Permalink
feat(Rate): add Rate component, close #218
Browse files Browse the repository at this point in the history
  • Loading branch information
Javey committed Mar 1, 2019
1 parent 22db05a commit a64c66e
Show file tree
Hide file tree
Showing 17 changed files with 438 additions and 5 deletions.
2 changes: 1 addition & 1 deletion components/input/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import './index.styl';
import {selectInput} from '../utils';

export default class Input extends Intact {
@Intact.template
@Intact.template()
static template = template;

static propTypes = {
Expand Down
27 changes: 27 additions & 0 deletions components/rate/demos/basic.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
title: 基础用法
order: 0
---

通过`value`设置组件的值,当添加`half`属性时,支持选中半星

```vdt
import Rate from 'kpc/components/rate';
<div>
<Rate v-model="value1" />
<br />
<Rate v-model="value2" half />
</div>
```

```js
export default class extends Intact {
@Intact.template()
static template = template;

defaults() {
return {value1: 2, value2: 2.5};
}
}
```
23 changes: 23 additions & 0 deletions components/rate/demos/clearable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
title: 可清除的
order: 2
---

添加`clearable`属性可以使组件在再次点击后清空值

```vdt
import Rate from 'kpc/components/rate';
<Rate v-model="value" clearable />
```

```js
export default class extends Intact {
@Intact.template()
static template = template;

defaults() {
return {value: 2};
}
}
```
26 changes: 26 additions & 0 deletions components/rate/demos/custom.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
title: 自定义图标
order: 3
---

通过`icon`扩展点,可以自定义图标

```vdt
import Rate from 'kpc/components/rate';
import Icon from 'kpc/components/icon';
<Rate v-model="value">
<b:icon><Icon class="ion-heart" /></b:icon>
</Rate>
```

```js
export default class extends Intact {
@Intact.template()
static template = template;

defaults() {
return {value: 2};
}
}
```
12 changes: 12 additions & 0 deletions components/rate/demos/disabled.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
title: 只读
order: 1
---

添加`disabled`属性,使组件变为只读状态

```vdt
import Rate from 'kpc/components/rate';
<Rate value={{ 2 }} disabled />
```
65 changes: 65 additions & 0 deletions components/rate/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import Intact from 'intact';
import template from './index.vdt';
import '../../styles/kpc.styl';
import './index.styl';

export default class Rate extends Intact {
@Intact.template()
static template = template;

static propTypes = {
value: Number,
count: Number,
disabled: Boolean,
half: false,
clearable: false,
};

defaults() {
return {
value: 0,
count: 5,
disabled: false,
half: false,
clearable: false,

_value: 0,
};
}

_init() {
this.on('$receive:value', (c, v) => {
if (!this.get('half')) v = Math.round(v);
this.set({
'_value': v,
'value': v,
});
});
}

onClick(value) {
if (this.get('disabled')) return;

// clear the value when click again on the clearable component
if (this.get('clearable') && this.get('value') === value) {
value = 0;
}

this.set({
'value': value,
'_value': value,
});
}

onMouseEnter(value) {
if (this.get('disabled')) return;

this.set('_value', value);
}

onMouseLeaveComponent() {
if (this.get('disabled')) return;

this.set('_value', this.get('value'));
}
}
22 changes: 22 additions & 0 deletions components/rate/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
title: 评分
category: 组件
order: 2
sidebar: doc
---

# 属性

| 属性 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| value | 组件取值 | `Number` | `0` |
| count | 星星的个数 | `Number` | `5` |
| disabled | 是否变为只读状态 | `Boolean` | `false` |
| half | 是否支持选中半星 | `Boolean` | `false` |
| clearable | 是否可以清空值 | `Boolean` | `false` |

# 扩展点

| 名称 | 说明 |
| --- | --- |
| icon | 自定义图标 |
65 changes: 65 additions & 0 deletions components/rate/index.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import ClearableDemo from '~/components/rate/demos/clearable';
import BasicDemo from '~/components/rate/demos/basic';
import DisabledDemo from '~/components/rate/demos/disabled';
import {mount, unmount, dispatchEvent} from 'test/utils';

describe('Rate', () => {
let instance;

// afterEach(() => unmount(instance));

it('should change value on click', () => {
instance = mount(BasicDemo);

const [rate1, rate2] = instance.element.querySelectorAll('.k-rate');

const [first1, second1] = rate1.querySelectorAll('.k-item:nth-child(4) > div');
first1.click();
expect(instance.get('value1')).to.eql(4);
second1.click();
expect(instance.get('value1')).to.eql(4);

// should fix value
instance.set('value1', 3.5);
expect(instance.get('value1')).to.eql(4);

// half
const [first2, second2] = rate2.querySelectorAll('.k-item:nth-child(4) > div');
first2.click();
expect(instance.get('value2')).to.eql(3.5);
second2.click();
expect(instance.get('value2')).to.eql(4);

// enter
const first = rate1.querySelector('.k-first');
dispatchEvent(first, 'mouseenter');
expect(rate1.innerHTML).to.matchSnapshot();
// leave
dispatchEvent(rate1, 'mouseleave');
expect(rate1.innerHTML).to.matchSnapshot();
});

it('should clear value when click again on the clearable component', () => {
instance = mount(ClearableDemo);

const first = instance.element.querySelector('.k-first');
first.click();
expect(instance.get('value')).to.eql(1);

first.click();
expect(instance.get('value')).to.eql(0);
});

it('disabled', () => {
instance = mount(DisabledDemo);

const first = instance.element.querySelector('.k-first');
first.click();
expect(instance.element.innerHTML).to.matchSnapshot();
dispatchEvent(first, 'mouseenter');
expect(instance.element.innerHTML).to.matchSnapshot();
// leave
dispatchEvent(instance.element, 'mouseleave');
expect(instance.element.innerHTML).to.matchSnapshot();
});
});
36 changes: 36 additions & 0 deletions components/rate/index.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
@require('./variables.styl')

.k-rate
display inline-block
.k-item
display inline-block
margin-right $rate-item-margin-right
cursor pointer
position relative
color $rate-color
transition all $transition
&:hover
transform $rate-item-hover-transform
.k-first
position absolute
top 0
left 0
width 50%
height 100%
overflow hidden
.k-icon
font-size $rate-icon-font-size
.k-full
color $rate-active-color
.k-half
.k-first
color $rate-active-color
// disabled
&.k-disabled
.k-item
cursor default
&:hover
transform none


requireTheme('rate')
41 changes: 41 additions & 0 deletions components/rate/index.vdt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import Icon from '../icon';

const {
_value, count, className,
style, disabled, half
} = self.get();

const classNameObj = {
'k-rate': true,
'k-disabled': disabled,
[className]: className,
};

const icon = <b:icon><Icon class="ion-android-star" /></b:icon>

<div className={{ classNameObj }} style={{ style }}
ev-mouseleave={{ self.onMouseLeaveComponent }}
>
{{ (() => {
const ret = [];
for (let i = 0; i < count; i++) {
const className = _value >= i + 1 ?
'k-full' : _value === i + 0.5 ?
'k-half' : null;
const halfStep = half ? i + 0.5 : i + 1;
ret.push(
<div class={{ {"k-item": true, [className]: className } }}>
<div class="k-first"
ev-click={{ self.onClick.bind(self, halfStep) }}
ev-mouseenter={{ self.onMouseEnter.bind(self, halfStep) }}
>{{ icon }}</div>
<div class="k-second"
ev-click={{ self.onClick.bind(self, i + 1) }}
ev-mouseenter={{ self.onMouseEnter.bind(self, i + 1) }}
>{{ icon }}</div>
</div>
);
}
return ret;
})() }}
</div>
8 changes: 8 additions & 0 deletions components/rate/variables.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@require('../../styles/themes/default.styl')

$rate-item-margin-right := unit(8 / 14, rem)
$rate-item-hover-transform := scale(1.1)
$rate-color := #ccc
$rate-active-color := $warning-color
$rate-icon-font-size := unit(24 / 14, rem)

6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@
"@babel/runtime-corejs2": "^7.2.0",
"downloadjs": "^1.4.7",
"enquire.js": "^2.1.6",
"intact": "^2.4.10",
"intact": "^2.4.11",
"intact-react": "^1.1.13",
"intact-vue": "^0.4.12",
"resize-observer-polyfill": "^1.5.0"
Expand Down
4 changes: 4 additions & 0 deletions scripts/doc.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ module.exports = function(isDev = true) {
ctx.hook.add('dist.after', async files => {
await ctx.fsEach(async function(file) {
if (/demos/.test(file.path)) {
if (!file.md.setting) return;

const iframe = file.md.setting.iframe;
await file.md.codes.forEach(async item => {
if (item.ignored) return;
Expand Down Expand Up @@ -348,6 +350,8 @@ module.exports = function(isDev = true) {
const iframes = [];
if (isDev) {
await ctx.fsEach(async function(file) {
if (!file.md.setting) return;

if (!/demos/.test(file.path)) {
file.extname = '.html';
await ctx.fsWrite(
Expand Down
Loading

0 comments on commit a64c66e

Please sign in to comment.