feat: radio && rate && spin
parent
16409c6ed1
commit
1af8349504
|
@ -2,6 +2,7 @@ import classNames from 'classnames';
|
|||
import PropTypes from '../_util/vue-types';
|
||||
import Radio from './Radio';
|
||||
import { getOptionProps, filterEmpty, hasProp } from '../_util/props-util';
|
||||
import { ConfigConsumerProps } from '../config-provider';
|
||||
function noop() {}
|
||||
|
||||
export default {
|
||||
|
@ -11,7 +12,6 @@ export default {
|
|||
},
|
||||
props: {
|
||||
prefixCls: {
|
||||
default: 'ant-radio',
|
||||
type: String,
|
||||
},
|
||||
defaultValue: PropTypes.any,
|
||||
|
@ -41,6 +41,9 @@ export default {
|
|||
radioGroupContext: this,
|
||||
};
|
||||
},
|
||||
inject: {
|
||||
configProvider: { default: () => ({}) },
|
||||
},
|
||||
computed: {
|
||||
radioOptions() {
|
||||
const { disabled } = this;
|
||||
|
@ -79,7 +82,10 @@ export default {
|
|||
render() {
|
||||
const { mouseenter = noop, mouseleave = noop } = this.$listeners;
|
||||
const props = getOptionProps(this);
|
||||
const { prefixCls, options, buttonStyle } = props;
|
||||
const { prefixCls: customizePrefixCls, options, buttonStyle } = props;
|
||||
const getPrefixCls = this.configProvider.getPrefixCls || ConfigConsumerProps.getPrefixCls;
|
||||
const prefixCls = getPrefixCls('radio', customizePrefixCls);
|
||||
|
||||
const groupPrefixCls = `${prefixCls}-group`;
|
||||
const classString = classNames(groupPrefixCls, `${groupPrefixCls}-${buttonStyle}`, {
|
||||
[`${groupPrefixCls}-${props.size}`]: props.size,
|
||||
|
|
|
@ -2,6 +2,7 @@ import PropTypes from '../_util/vue-types';
|
|||
import VcCheckbox from '../vc-checkbox';
|
||||
import classNames from 'classnames';
|
||||
import { getOptionProps, getAttrs } from '../_util/props-util';
|
||||
import { ConfigConsumerProps } from '../config-provider';
|
||||
|
||||
function noop() {}
|
||||
|
||||
|
@ -12,7 +13,6 @@ export default {
|
|||
},
|
||||
props: {
|
||||
prefixCls: {
|
||||
default: 'ant-radio',
|
||||
type: String,
|
||||
},
|
||||
defaultChecked: Boolean,
|
||||
|
@ -27,6 +27,7 @@ export default {
|
|||
},
|
||||
inject: {
|
||||
radioGroupContext: { default: undefined },
|
||||
configProvider: { default: () => ({}) },
|
||||
},
|
||||
methods: {
|
||||
handleChange(event) {
|
||||
|
@ -47,7 +48,10 @@ export default {
|
|||
const props = getOptionProps(this);
|
||||
const children = $slots.default;
|
||||
const { mouseenter = noop, mouseleave = noop, ...restListeners } = $listeners;
|
||||
const { prefixCls, ...restProps } = props;
|
||||
const { prefixCls: customizePrefixCls, ...restProps } = props;
|
||||
const getPrefixCls = this.configProvider.getPrefixCls || ConfigConsumerProps.getPrefixCls;
|
||||
const prefixCls = getPrefixCls('radio', customizePrefixCls);
|
||||
|
||||
const radioProps = {
|
||||
props: { ...restProps, prefixCls },
|
||||
on: restListeners,
|
||||
|
|
|
@ -1,21 +1,28 @@
|
|||
import Radio from './Radio';
|
||||
import { getOptionProps } from '../_util/props-util';
|
||||
import { ConfigConsumerProps } from '../config-provider';
|
||||
|
||||
export default {
|
||||
name: 'ARadioButton',
|
||||
props: {
|
||||
...Radio.props,
|
||||
prefixCls: {
|
||||
default: 'ant-radio-button',
|
||||
type: String,
|
||||
},
|
||||
},
|
||||
inject: {
|
||||
radioGroupContext: { default: undefined },
|
||||
configProvider: { default: () => ({}) },
|
||||
},
|
||||
render() {
|
||||
const props = getOptionProps(this);
|
||||
const radioProps = { props, on: { ...this.$listeners } };
|
||||
const {prefixCls: customizePrefixCls, ...otherProps} = getOptionProps(this);
|
||||
const getPrefixCls = this.configProvider.getPrefixCls || ConfigConsumerProps.getPrefixCls;
|
||||
const prefixCls = getPrefixCls('radio-button', customizePrefixCls);
|
||||
|
||||
const radioProps = { props: {
|
||||
...otherProps,
|
||||
prefixCls,
|
||||
}, on: { ...this.$listeners } };
|
||||
if (this.radioGroupContext) {
|
||||
radioProps.on.change = this.radioGroupContext.onRadioChange;
|
||||
radioProps.props.checked = props.value === this.radioGroupContext.stateValue;
|
||||
|
|
|
@ -11,8 +11,8 @@ Add copywriting in rate components.
|
|||
```html
|
||||
<template>
|
||||
<span>
|
||||
<a-rate v-model='value'/>
|
||||
<span class="ant-rate-text">{{value}} stars</span>
|
||||
<a-rate :tooltips="desc" v-model='value'/>
|
||||
<span class="ant-rate-text">{{desc[value - 1]}}</span>
|
||||
</span>
|
||||
</template>
|
||||
<script>
|
||||
|
@ -20,6 +20,7 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
value: 3,
|
||||
desc: ['terrible', 'bad', 'normal', 'good', 'wonderful']
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
| count | star count | number | 5 |
|
||||
| defaultValue | default value | number | 0 |
|
||||
| disabled | read only, unable to interact | boolean | false |
|
||||
| tooltips | Customize tooltip by each character | string\[] | - |
|
||||
| value(v-model) | current value | number | - |
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
|
||||
import omit from 'omit.js';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import { initDefaultProps, getOptionProps, getComponentFromProp } from '../_util/props-util';
|
||||
import { getOptionProps, getComponentFromProp } from '../_util/props-util';
|
||||
import { ConfigConsumerProps } from '../config-provider';
|
||||
import VcRate from '../vc-rate';
|
||||
import Icon from '../icon';
|
||||
import Tooltip from '../tooltip';
|
||||
|
||||
export const RateProps = {
|
||||
prefixCls: PropTypes.string,
|
||||
|
@ -10,6 +14,7 @@ export const RateProps = {
|
|||
defaultValue: PropTypes.value,
|
||||
allowHalf: PropTypes.bool,
|
||||
allowClear: PropTypes.bool,
|
||||
tooltips: PropTypes.arrayOf(PropTypes.string),
|
||||
disabled: PropTypes.bool,
|
||||
character: PropTypes.any,
|
||||
autoFocus: PropTypes.bool,
|
||||
|
@ -21,9 +26,10 @@ const Rate = {
|
|||
prop: 'value',
|
||||
event: 'change',
|
||||
},
|
||||
props: initDefaultProps(RateProps, {
|
||||
prefixCls: 'ant-rate',
|
||||
}),
|
||||
props: RateProps,
|
||||
inject: {
|
||||
configProvider: { default: () => ({}) },
|
||||
},
|
||||
methods: {
|
||||
focus() {
|
||||
this.$refs.refRate.focus();
|
||||
|
@ -31,15 +37,31 @@ const Rate = {
|
|||
blur() {
|
||||
this.$refs.refRate.blur();
|
||||
},
|
||||
characterRender(node, { index }) {
|
||||
const { tooltips } = this.$props;
|
||||
if (!tooltips) return node;
|
||||
const tooltipsProps = {
|
||||
props: {
|
||||
title: tooltips[index],
|
||||
},
|
||||
};
|
||||
return <Tooltip {...tooltipsProps}>{node}</Tooltip>;
|
||||
},
|
||||
},
|
||||
render() {
|
||||
const { prefixCls: customizePrefixCls, ...restProps } = getOptionProps(this);
|
||||
const getPrefixCls = this.configProvider.getPrefixCls || ConfigConsumerProps.getPrefixCls;
|
||||
const prefixCls = getPrefixCls('rate', customizePrefixCls);
|
||||
|
||||
const character = getComponentFromProp(this, 'character') || (
|
||||
<Icon type="star" theme="filled" />
|
||||
);
|
||||
const rateProps = {
|
||||
props: {
|
||||
character,
|
||||
...getOptionProps(this),
|
||||
characterRender: this.characterRender,
|
||||
prefixCls,
|
||||
...omit(restProps, ['tooltips']),
|
||||
},
|
||||
on: this.$listeners,
|
||||
ref: 'refRate',
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
| count | star 总数 | number | 5 |
|
||||
| defaultValue | 默认值 | number | 0 |
|
||||
| disabled | 只读,无法进行交互 | boolean | false |
|
||||
| tooltips | 自定义每项的提示信息 | string\[] | - |
|
||||
| value(v-model) | 当前数,受控值 | number | - |
|
||||
|
||||
### 事件
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import debounce from 'lodash/debounce';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import BaseMixin from '../_util/BaseMixin';
|
||||
import {
|
||||
|
@ -7,6 +8,7 @@ import {
|
|||
getComponentFromProp,
|
||||
} from '../_util/props-util';
|
||||
import { cloneElement } from '../_util/vnode';
|
||||
import { ConfigConsumerProps } from '../config-provider';
|
||||
|
||||
export const SpinSize = PropTypes.oneOf(['small', 'default', 'large']);
|
||||
|
||||
|
@ -40,56 +42,43 @@ export default {
|
|||
name: 'ASpin',
|
||||
mixins: [BaseMixin],
|
||||
props: initDefaultProps(SpinProps(), {
|
||||
prefixCls: 'ant-spin',
|
||||
size: 'default',
|
||||
spinning: true,
|
||||
wrapperClassName: '',
|
||||
}),
|
||||
inject: {
|
||||
configProvider: { default: () => ({}) },
|
||||
},
|
||||
data() {
|
||||
const { spinning, delay } = this;
|
||||
this.debounceTimeout = null;
|
||||
this.delayTimeout = null;
|
||||
this.originalUpdateSpinning = this.updateSpinning;
|
||||
this.debouncifyUpdateSpinning(this.$props);
|
||||
return {
|
||||
sSpinning: spinning && !shouldDelay(spinning, delay),
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.updateSpinning();
|
||||
},
|
||||
updated() {
|
||||
this.$nextTick(() => {
|
||||
const { delay, spinning, sSpinning } = this;
|
||||
if (sSpinning === spinning) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.debounceTimeout) {
|
||||
clearTimeout(this.debounceTimeout);
|
||||
}
|
||||
if (sSpinning && !spinning) {
|
||||
this.debounceTimeout = window.setTimeout(() => this.setState({ sSpinning: spinning }), 200);
|
||||
if (this.delayTimeout) {
|
||||
clearTimeout(this.delayTimeout);
|
||||
}
|
||||
} else {
|
||||
if (shouldDelay(spinning, delay)) {
|
||||
if (this.delayTimeout) {
|
||||
clearTimeout(this.delayTimeout);
|
||||
}
|
||||
this.delayTimeout = window.setTimeout(this.delayUpdateSpinning, delay);
|
||||
} else {
|
||||
this.setState({ sSpinning: spinning });
|
||||
}
|
||||
}
|
||||
this.debouncifyUpdateSpinning();
|
||||
this.updateSpinning();
|
||||
});
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.debounceTimeout) {
|
||||
clearTimeout(this.debounceTimeout);
|
||||
}
|
||||
if (this.delayTimeout) {
|
||||
clearTimeout(this.delayTimeout);
|
||||
if (this.updateSpinning && this.updateSpinning.cancel) {
|
||||
this.updateSpinning.cancel();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
delayUpdateSpinning() {
|
||||
debouncifyUpdateSpinning(props) {
|
||||
const { delay } = props || this.$props;
|
||||
if(delay) {
|
||||
this.updateSpinning = debounce(this.originalUpdateSpinning, delay);
|
||||
}
|
||||
},
|
||||
updateSpinning() {
|
||||
const { spinning, sSpinning } = this;
|
||||
if (sSpinning !== spinning) {
|
||||
this.setState({ sSpinning: spinning });
|
||||
|
@ -101,9 +90,8 @@ export default {
|
|||
}
|
||||
return null;
|
||||
},
|
||||
renderIndicator(h, props) {
|
||||
renderIndicator(h, prefixCls) {
|
||||
// const h = this.$createElement
|
||||
const { prefixCls } = props;
|
||||
const dotClassName = `${prefixCls}-dot`;
|
||||
let indicator = getComponentFromProp(this, 'indicator');
|
||||
if (Array.isArray(indicator)) {
|
||||
|
@ -129,7 +117,10 @@ export default {
|
|||
},
|
||||
},
|
||||
render(h) {
|
||||
const { size, prefixCls, tip, wrapperClassName, ...restProps } = this.$props;
|
||||
const { size, prefixCls: customizePrefixCls, tip, wrapperClassName, ...restProps } = this.$props;
|
||||
const getPrefixCls = this.configProvider.getPrefixCls || ConfigConsumerProps.getPrefixCls;
|
||||
const prefixCls = getPrefixCls('spin', customizePrefixCls);
|
||||
|
||||
const { sSpinning } = this;
|
||||
const spinClassName = {
|
||||
[prefixCls]: true,
|
||||
|
@ -141,7 +132,7 @@ export default {
|
|||
|
||||
const spinElement = (
|
||||
<div {...restProps} class={spinClassName}>
|
||||
{this.renderIndicator(h, this.$props)}
|
||||
{this.renderIndicator(h, prefixCls)}
|
||||
{tip ? <div class={`${prefixCls}-text`}>{tip}</div> : null}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -32,25 +32,6 @@ describe('Spin', () => {
|
|||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should render with delay when it's mounted with spinning=true and delay", async () => {
|
||||
const props = {
|
||||
propsData: {
|
||||
delay: 500,
|
||||
spinning: true,
|
||||
},
|
||||
sync: false,
|
||||
};
|
||||
const wrapper = mount(Spin, props);
|
||||
await asyncExpect(() => {
|
||||
expect(
|
||||
wrapper
|
||||
.find('.ant-spin')
|
||||
.classes()
|
||||
.includes('ant-spin-spinning'),
|
||||
).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('should be controlled by spinning', async () => {
|
||||
const props = {
|
||||
propsData: {
|
||||
|
|
Loading…
Reference in New Issue