Merge branch 'feat-3.10.3' of https://github.com/vueComponent/ant-design into feat-3.10.3

pull/309/head
tangjinzhou 2018-12-04 09:45:10 +08:00
commit e51a6e9691
28 changed files with 334 additions and 171 deletions

View File

@ -5,11 +5,11 @@ exports[`Cascader can be selected 1`] = `
<div class="ant-cascader-menus ant-cascader-menus-placement-bottomLeft" style="left: -999px; top: -995px;">
<div class="ant-cascader-menus-content">
<ul class="ant-cascader-menu">
<li title="Zhejiang" class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active">Zhejiang<span class="ant-cascader-menu-item-expand-icon">&gt;</span></li>
<li title="Jiangsu" class="ant-cascader-menu-item ant-cascader-menu-item-expand">Jiangsu<span class="ant-cascader-menu-item-expand-icon">&gt;</span></li>
<li title="Zhejiang" class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active">Zhejiang<span class="ant-cascader-menu-item-expand-icon"><i class="anticon anticon-right"><svg viewBox="64 64 896 896" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" class=""><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"></path></svg></i></span></li>
<li title="Jiangsu" class="ant-cascader-menu-item ant-cascader-menu-item-expand">Jiangsu<span class="ant-cascader-menu-item-expand-icon"><i class="anticon anticon-right"><svg viewBox="64 64 896 896" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" class=""><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"></path></svg></i></span></li>
</ul>
<ul class="ant-cascader-menu">
<li title="Hangzhou" class="ant-cascader-menu-item ant-cascader-menu-item-expand">Hangzhou<span class="ant-cascader-menu-item-expand-icon">&gt;</span></li>
<li title="Hangzhou" class="ant-cascader-menu-item ant-cascader-menu-item-expand">Hangzhou<span class="ant-cascader-menu-item-expand-icon"><i class="anticon anticon-right"><svg viewBox="64 64 896 896" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" class=""><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"></path></svg></i></span></li>
</ul>
</div>
</div>
@ -21,11 +21,11 @@ exports[`Cascader can be selected 2`] = `
<div class="ant-cascader-menus ant-cascader-menus-placement-bottomLeft" style="left: -999px; top: -995px;">
<div class="ant-cascader-menus-content">
<ul class="ant-cascader-menu">
<li title="Zhejiang" class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active">Zhejiang<span class="ant-cascader-menu-item-expand-icon">&gt;</span></li>
<li title="Jiangsu" class="ant-cascader-menu-item ant-cascader-menu-item-expand">Jiangsu<span class="ant-cascader-menu-item-expand-icon">&gt;</span></li>
<li title="Zhejiang" class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active">Zhejiang<span class="ant-cascader-menu-item-expand-icon"><i class="anticon anticon-right"><svg viewBox="64 64 896 896" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" class=""><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"></path></svg></i></span></li>
<li title="Jiangsu" class="ant-cascader-menu-item ant-cascader-menu-item-expand">Jiangsu<span class="ant-cascader-menu-item-expand-icon"><i class="anticon anticon-right"><svg viewBox="64 64 896 896" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" class=""><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"></path></svg></i></span></li>
</ul>
<ul class="ant-cascader-menu">
<li title="Hangzhou" class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active">Hangzhou<span class="ant-cascader-menu-item-expand-icon">&gt;</span></li>
<li title="Hangzhou" class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active">Hangzhou<span class="ant-cascader-menu-item-expand-icon"><i class="anticon anticon-right"><svg viewBox="64 64 896 896" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" class=""><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"></path></svg></i></span></li>
</ul>
<ul class="ant-cascader-menu">
<li title="West Lake" class="ant-cascader-menu-item">West Lake</li>
@ -40,11 +40,11 @@ exports[`Cascader can be selected 3`] = `
<div class="ant-cascader-menus ant-cascader-menus-placement-bottomLeft" style="display: none;">
<div class="ant-cascader-menus-content">
<ul class="ant-cascader-menu">
<li title="Zhejiang" class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active">Zhejiang<span class="ant-cascader-menu-item-expand-icon">&gt;</span></li>
<li title="Jiangsu" class="ant-cascader-menu-item ant-cascader-menu-item-expand">Jiangsu<span class="ant-cascader-menu-item-expand-icon">&gt;</span></li>
<li title="Zhejiang" class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active">Zhejiang<span class="ant-cascader-menu-item-expand-icon"><i class="anticon anticon-right"><svg viewBox="64 64 896 896" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" class=""><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"></path></svg></i></span></li>
<li title="Jiangsu" class="ant-cascader-menu-item ant-cascader-menu-item-expand">Jiangsu<span class="ant-cascader-menu-item-expand-icon"><i class="anticon anticon-right"><svg viewBox="64 64 896 896" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" class=""><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"></path></svg></i></span></li>
</ul>
<ul class="ant-cascader-menu">
<li title="Hangzhou" class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active">Hangzhou<span class="ant-cascader-menu-item-expand-icon">&gt;</span></li>
<li title="Hangzhou" class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active">Hangzhou<span class="ant-cascader-menu-item-expand-icon"><i class="anticon anticon-right"><svg viewBox="64 64 896 896" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" class=""><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"></path></svg></i></span></li>
</ul>
<ul class="ant-cascader-menu">
<li title="West Lake" class="ant-cascader-menu-item ant-cascader-menu-item-active">West Lake</li>
@ -67,8 +67,8 @@ exports[`Cascader popup correctly when panel is open 1`] = `
<div class="ant-cascader-menus ant-cascader-menus-placement-bottomLeft" style="left: -999px; top: -995px;">
<div class="ant-cascader-menus-content">
<ul class="ant-cascader-menu">
<li title="Zhejiang" class="ant-cascader-menu-item ant-cascader-menu-item-expand">Zhejiang<span class="ant-cascader-menu-item-expand-icon">&gt;</span></li>
<li title="Jiangsu" class="ant-cascader-menu-item ant-cascader-menu-item-expand">Jiangsu<span class="ant-cascader-menu-item-expand-icon">&gt;</span></li>
<li title="Zhejiang" class="ant-cascader-menu-item ant-cascader-menu-item-expand">Zhejiang<span class="ant-cascader-menu-item-expand-icon"><i class="anticon anticon-right"><svg viewBox="64 64 896 896" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" class=""><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"></path></svg></i></span></li>
<li title="Jiangsu" class="ant-cascader-menu-item ant-cascader-menu-item-expand">Jiangsu<span class="ant-cascader-menu-item-expand-icon"><i class="anticon anticon-right"><svg viewBox="64 64 896 896" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" class=""><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"></path></svg></i></span></li>
</ul>
</div>
</div>
@ -80,11 +80,11 @@ exports[`Cascader popup correctly with defaultValue 1`] = `
<div class="ant-cascader-menus ant-cascader-menus-placement-bottomLeft" style="left: -999px; top: -995px;">
<div class="ant-cascader-menus-content">
<ul class="ant-cascader-menu">
<li title="Zhejiang" class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active">Zhejiang<span class="ant-cascader-menu-item-expand-icon">&gt;</span></li>
<li title="Jiangsu" class="ant-cascader-menu-item ant-cascader-menu-item-expand">Jiangsu<span class="ant-cascader-menu-item-expand-icon">&gt;</span></li>
<li title="Zhejiang" class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active">Zhejiang<span class="ant-cascader-menu-item-expand-icon"><i class="anticon anticon-right"><svg viewBox="64 64 896 896" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" class=""><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"></path></svg></i></span></li>
<li title="Jiangsu" class="ant-cascader-menu-item ant-cascader-menu-item-expand">Jiangsu<span class="ant-cascader-menu-item-expand-icon"><i class="anticon anticon-right"><svg viewBox="64 64 896 896" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" class=""><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"></path></svg></i></span></li>
</ul>
<ul class="ant-cascader-menu">
<li title="Hangzhou" class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active">Hangzhou<span class="ant-cascader-menu-item-expand-icon">&gt;</span></li>
<li title="Hangzhou" class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active">Hangzhou<span class="ant-cascader-menu-item-expand-icon"><i class="anticon anticon-right"><svg viewBox="64 64 896 896" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" class=""><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"></path></svg></i></span></li>
</ul>
<ul class="ant-cascader-menu">
<li title="West Lake" class="ant-cascader-menu-item">West Lake</li>
@ -95,8 +95,9 @@ exports[`Cascader popup correctly with defaultValue 1`] = `
`;
exports[`Cascader support controlled mode 1`] = `
<span tabindex="0" class="ant-cascader-picker"><input value="" type="text" readonly="true" class="ant-input ant-cascader-input ant-cascader-input "><span class="ant-cascader-picker-label">Zhejiang / Hangzhou / West Lake</span><i class="anticon anticon-cross-circle">
<!----></i><i class="anticon anticon-down"><svg viewBox="64 64 896 896" data-icon="down" width="1em" height="1em" fill="currentColor" aria-hidden="true" class="">
<span tabindex="0" class="ant-cascader-picker"><input value="" type="text" readonly="true" class="ant-input ant-cascader-input ant-cascader-input "><span class="ant-cascader-picker-label">Zhejiang / Hangzhou / West Lake</span><i class="ant-cascader-picker-clear anticon anticon-close-circle"><svg viewBox="64 64 896 896" data-icon="close-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" class="">
<path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 0 1-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"></path>
</svg></i><i class="ant-cascader-picker-arrow anticon anticon-down"><svg viewBox="64 64 896 896" data-icon="down" width="1em" height="1em" fill="currentColor" aria-hidden="true" class="">
<path d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"></path>
</svg></i></span>
`;

View File

@ -10,6 +10,7 @@ import Lazy from './lazy'
import Search from './search'
import Size from './size'
import FieldsName from './fields-name'
import Suffix from './suffix'
import CN from '../index.zh-CN.md'
import US from '../index.en-US.md'
@ -33,6 +34,7 @@ const md = {
export default {
category: 'Components',
type: 'Data Entry',
zhType: '数据录入',
title: 'Cascader',
subtitle: '级联选择',
render () {
@ -50,6 +52,7 @@ export default {
<Search/>
<Size/>
<FieldsName />
<Suffix />
<api>
<CN slot='cn' />
<US/>

View File

@ -0,0 +1,58 @@
<cn>
#### 后缀图标
省市区级联。
</cn>
<us>
#### Suffix
Cascade selection box for selecting province/city/district.
</us>
```html
<template>
<div>
<a-cascader style="margin-top: 1rem" :options="options" @change="onChange" placeholder="Please select">
<a-icon type="smile" slot="suffixIcon" class="test"/>
</a-cascader>
<a-cascader suffixIcon="ab" style="margin-top: 1rem" :options="options" @change="onChange" placeholder="Please select" />
</div>
</template>
<script>
export default {
data() {
return {
options: [{
value: 'zhejiang',
label: 'Zhejiang',
children: [{
value: 'hangzhou',
label: 'Hangzhou',
children: [{
value: 'xihu',
label: 'West Lake',
}],
}],
}, {
value: 'jiangsu',
label: 'Jiangsu',
children: [{
value: 'nanjing',
label: 'Nanjing',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
}],
}],
}]
}
},
methods: {
onChange(value) {
console.log(value);
}
}
}
</script>
```

View File

@ -26,6 +26,7 @@
| popupVisible | set visible of cascader popup | boolean | - |
| showSearch | Whether show search input in single mode. | boolean\|object | false |
| size | input size, one of `large` `default` `small` | string | `default` |
| suffixIcon | The custom suffix icon | string \| VNode \| slot | - |
| value(v-model) | selected value | string\[] | - |
Fields in `showSearch`:

View File

@ -7,8 +7,9 @@ import omit from 'omit.js'
import KeyCode from '../_util/KeyCode'
import Input from '../input'
import Icon from '../icon'
import { hasProp, filterEmpty, getOptionProps, getStyle, getClass, getAttrs } from '../_util/props-util'
import { hasProp, filterEmpty, getOptionProps, getStyle, getClass, getAttrs, getComponentFromProp, isValidElement } from '../_util/props-util'
import BaseMixin from '../_util/BaseMixin'
import { cloneElement } from '../_util/vnode'
const CascaderOptionType = PropTypes.shape({
value: PropTypes.string,
@ -74,6 +75,7 @@ const CascaderProps = {
popupVisible: PropTypes.bool,
fieldNames: FieldNamesType,
autoFocus: PropTypes.bool,
suffixIcon: PropTypes.any,
}
function defaultFilterOption (inputValue, path, names) {
@ -88,7 +90,7 @@ function defaultSortFilteredOption (a, b, inputValue, names) {
return a.findIndex(callback) - b.findIndex(callback)
}
function getFilledFieldNames (fieldNames = {}) {
function getFilledFieldNames ({ fieldNames = {}}) {
const names = {
children: fieldNames.children || 'children',
label: fieldNames.label || 'label',
@ -110,13 +112,13 @@ const Cascader = {
},
data () {
this.cachedOptions = []
const { value, defaultValue, popupVisible, showSearch, options, changeOnSelect, flattenTree, fieldNames } = this
const { value, defaultValue, popupVisible, showSearch, options, flattenTree } = this
return {
sValue: value || defaultValue || [],
inputValue: '',
inputFocused: false,
sPopupVisible: popupVisible,
flattenOptions: showSearch ? flattenTree(options, changeOnSelect, fieldNames) : undefined,
flattenOptions: showSearch ? flattenTree(options, this.$props) : undefined,
}
},
mounted () {
@ -135,7 +137,7 @@ const Cascader = {
},
options (val) {
if (this.showSearch) {
this.setState({ flattenOptions: this.flattenTree(this.options, this.changeOnSelect, this.fieldNames) })
this.setState({ flattenOptions: this.flattenTree(this.options, this.$props) })
}
},
},
@ -218,8 +220,8 @@ const Cascader = {
},
getLabel () {
const { options, $scopedSlots, fieldNames } = this
const names = getFilledFieldNames(fieldNames)
const { options, $scopedSlots } = this
const names = getFilledFieldNames(this.$props)
const displayRender = this.displayRender || $scopedSlots.displayRender || defaultDisplayRender
const value = this.sValue
const unwrappedValue = Array.isArray(value[0]) ? value[0] : value
@ -242,18 +244,18 @@ const Cascader = {
}
},
flattenTree (options, changeOnSelect, fieldNames, ancestor = []) {
const names = getFilledFieldNames(fieldNames)
flattenTree (options, props, ancestor = []) {
const names = getFilledFieldNames(props)
let flattenOptions = []
const childrenName = names.children
options.forEach((option) => {
const path = ancestor.concat(option)
if (changeOnSelect || !option[childrenName] || !option[childrenName].length) {
if (props.changeOnSelect || !option[childrenName] || !option[childrenName].length) {
flattenOptions.push(path)
}
if (option[childrenName]) {
flattenOptions = flattenOptions.concat(
this.flattenTree(option[childrenName], changeOnSelect, fieldNames, path)
this.flattenTree(option[childrenName], props, path)
)
}
})
@ -261,8 +263,8 @@ const Cascader = {
},
generateFilteredOptions (prefixCls) {
const { showSearch, notFoundContent, $scopedSlots, fieldNames } = this
const names = getFilledFieldNames(fieldNames)
const { showSearch, notFoundContent, $scopedSlots } = this
const names = getFilledFieldNames(this.$props)
const {
filter = defaultFilterOption,
// render = this.defaultRenderFilteredOption,
@ -308,6 +310,7 @@ const Cascader = {
const { $slots, sPopupVisible, inputValue, $listeners } = this
const { sValue: value, inputFocused } = this.$data
const props = getOptionProps(this)
const suffixIcon = getComponentFromProp(this, 'suffixIcon')
const {
prefixCls, inputPrefixCls, placeholder, size, disabled,
allowClear, showSearch = false, ...otherProps } = props
@ -318,7 +321,8 @@ const Cascader = {
})
const clearIcon = (allowClear && !disabled && value.length > 0) || inputValue ? (
<Icon
type='cross-circle'
type='close-circle'
theme='filled'
class={`${prefixCls}-picker-clear`}
onClick={this.clearSelection}
key='clear-icon'
@ -403,6 +407,19 @@ const Cascader = {
attrs: getAttrs(this),
}
const children = filterEmpty($slots.default)
const inputIcon = suffixIcon && (
isValidElement(suffixIcon[0])
? cloneElement(
suffixIcon[0],
{
class: {
[`${prefixCls}-picker-arrow`]: true,
},
},
) : <span class={`${prefixCls}-picker-arrow`}>{suffixIcon}</span>) || (
<Icon type='down' class={arrowCls} />
)
const input = children.length ? children : (
<span
class={pickerCls}
@ -417,7 +434,17 @@ const Cascader = {
{this.getLabel()}
</span> : null}
{clearIcon}
<Icon type='down' key='down-icon' class={arrowCls} />
{inputIcon}
</span>
)
const expandIcon = (
<Icon type='right' />
)
const loadingIcon = (
<span class={`${prefixCls}-menu-item-loading-icon`}>
<Icon type='redo' spin />
</span>
)
const cascaderProps = {
@ -427,6 +454,8 @@ const Cascader = {
value: value,
popupVisible: sPopupVisible,
dropdownMenuColumnStyle: dropdownMenuColumnStyle,
expandIcon,
loadingIcon,
},
on: {
...$listeners,

View File

@ -26,6 +26,7 @@
| popupVisible | 控制浮层显隐 | boolean | - |
| showSearch | 在选择框中显示搜索框 | boolean | false |
| size | 输入框大小,可选 `large` `default` `small` | string | `default` |
| suffixIcon | 自定义的选择框后缀图标 | string \| VNode \| slot | - |
| value(v-model) | 指定选中项 | string\[] | - |
`showSearch` 为对象时,其中的字段:

View File

@ -55,7 +55,10 @@ export default {
} = props
const checkboxProps = { props: { ...restProps, prefixCls }, on: restListeners, attrs: getAttrs(this) }
if (checkboxGroup) {
checkboxProps.on.change = () => checkboxGroup.toggleOption({ label: children, value: props.value })
checkboxProps.on.change = (...args) => {
this.$emit('change', ...args)
checkboxGroup.toggleOption({ label: children, value: props.value })
}
checkboxProps.props.checked = checkboxGroup.sValue.indexOf(props.value) !== -1
checkboxProps.props.disabled = props.disabled || checkboxGroup.disabled
} else {

View File

@ -1,6 +1,7 @@
import Checkbox from './Checkbox'
import hasProp from '../_util/props-util'
function noop () {}
export default {
name: 'ACheckboxGroup',
props: {
@ -82,7 +83,7 @@ export default {
disabled={'disabled' in option ? option.disabled : props.disabled}
value={option.value}
checked={state.sValue.indexOf(option.value) !== -1}
onChange={() => this.toggleOption(option)}
onChange={option.onChange || noop}
class={`${groupPrefixCls}-item`}
>
{option.label}

View File

@ -103,4 +103,21 @@ describe('CheckboxGroup', () => {
expect(wrapper.vm.sValue).toEqual(['Apple'])
})
})
// https://github.com/ant-design/ant-design/issues/12642
it('should trigger onChange in sub Checkbox', () => {
const onChange = jest.fn()
const wrapper = mount({
render () {
return (
<Checkbox.Group>
<Checkbox value='my' onChange={onChange} />
</Checkbox.Group>
)
},
})
wrapper.findAll('.ant-checkbox-input').at(0).trigger('change')
expect(onChange).toBeCalled()
expect(onChange.mock.calls[0][0].target.value).toEqual('my')
})
})

View File

@ -29,6 +29,7 @@
category: 'Components',
subtitle: '多选框',
type: 'Data Entry',
zhType: '数据录入',
title: 'Checkbox',
render () {
return (

View File

@ -23,7 +23,7 @@
| -------- | ----------- | ---- | ------- |
| defaultValue | Default selected value | string\[] | \[] |
| disabled | Disable all checkboxes | boolean | false |
| options | Specifies options | string\[] \| Array&lt;{ label: string value: string disabled?: boolean }> | \[] |
| options | Specifies options | string\[] \| Array&lt;{ label: string value: string disabled?: boolean, onChange?: function }> | \[] |
| value | Used for setting the currently selected value. | string\[] | \[] |
#### events

View File

@ -25,9 +25,8 @@
| --- | --- | --- | --- |
| defaultValue | 默认选中的选项 | string\[] | \[] |
| disabled | 整组失效 | boolean | false |
| options | 指定可选项 | string\[] \| Array&lt;{ label: string value: string disabled?: boolean }> | \[] |
| options | 指定可选项 | string\[] \| Array&lt;{ label: string value: string disabled?: boolean, onChange?: function }> | \[] |
| value | 指定选中的选项 | string\[] | \[] |
| onChange | 变化时回调函数 | Function(checkedValue) | - |
#### 事件
| 事件名称 | 说明 | 回调参数 |

View File

@ -23,6 +23,7 @@ const md = {
export default {
category: 'Components',
type: 'Other',
zhType: '其他',
title: 'Divider',
subtitle: '分割线',
render () {

View File

@ -27,6 +27,7 @@ export default {
category: 'Components',
subtitle: '下拉菜单',
type: 'Navigation',
zhType: '导航',
title: 'Dropdown',
render () {
return (

View File

@ -11,7 +11,7 @@ import {
} from './utils'
import warning from '../_util/warning'
import { getTwoToneColor, setTwoToneColor } from './twoTonePrimaryColor'
import { filterEmpty } from '../_util/props-util'
import { filterEmpty, getClass } from '../_util/props-util'
// Initial setting
VueIcon.add(...Object.keys(allIcons).map((key) => allIcons[key]))
@ -51,6 +51,7 @@ const Icon = {
)
const classString = classNames({
...getClass(context),
[`anticon`]: true,
[`anticon-${type}`]: !!type,
})

View File

@ -20,6 +20,10 @@ export const SpinProps = () => ({
// Render indicator
let defaultIndicator
function shouldDelay (spinning, delay) {
return !!spinning && !!delay && !isNaN(Number(delay))
}
export function setDefaultIndicator (content) {
defaultIndicator = typeof content.indicator === 'function' ? content.indicator : (h) => {
return <content.indicator />
@ -36,14 +40,64 @@ export default {
wrapperClassName: '',
}),
data () {
const { spinning } = this
const { spinning, delay } = this
this.debounceTimeout = null
this.delayTimeout = null
return {
stateSpinning: spinning,
debounceTimeout: null,
delayTimeout: null,
sSpinning: spinning && !shouldDelay(spinning, delay),
}
},
mounted () {
this.$nextTick(() => {
const { spinning, delay } = this
if (shouldDelay(spinning, delay)) {
this.delayTimeout = window.setTimeout(this.delayUpdateSpinning, delay)
}
})
},
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 })
}
}
})
},
beforeDestroy () {
if (this.debounceTimeout) {
clearTimeout(this.debounceTimeout)
}
if (this.delayTimeout) {
clearTimeout(this.delayTimeout)
}
},
methods: {
delayUpdateSpinning () {
const { spinning, sSpinning } = this
if (sSpinning !== spinning) {
this.setState({ sSpinning: spinning })
}
},
getChildren () {
if (this.$slots && this.$slots.default) {
return filterEmpty(this.$slots.default)
@ -77,55 +131,14 @@ export default {
)
},
},
mounted () {
this.$nextTick(() => {
const { spinning, delay } = this
if (spinning && delay && !isNaN(Number(delay))) {
this.setState({ stateSpinning: false })
this.delayTimeout = window.setTimeout(() => this.setState({ stateSpinning: spinning }), delay)
}
})
},
beforeDestroy () {
if (this.debounceTimeout) {
clearTimeout(this.debounceTimeout)
}
if (this.delayTimeout) {
clearTimeout(this.delayTimeout)
}
},
watch: {
spinning () {
const { delay, spinning } = this
if (this.debounceTimeout) {
clearTimeout(this.debounceTimeout)
}
if (!spinning) {
this.debounceTimeout = window.setTimeout(() => this.setState({ stateSpinning: spinning }), 200)
if (this.delayTimeout) {
clearTimeout(this.delayTimeout)
}
} else {
if (spinning && delay && !isNaN(Number(delay))) {
if (this.delayTimeout) {
clearTimeout(this.delayTimeout)
}
this.delayTimeout = window.setTimeout(() => this.setState({ stateSpinning: spinning }), delay)
} else {
this.setState({ stateSpinning: spinning })
}
}
},
},
render (h) {
const { size, prefixCls, tip, wrapperClassName, ...restProps } = this.$props
const { stateSpinning } = this
const { sSpinning } = this
const spinClassName = {
[prefixCls]: true,
[`${prefixCls}-sm`]: size === 'small',
[`${prefixCls}-lg`]: size === 'large',
[`${prefixCls}-spinning`]: stateSpinning,
[`${prefixCls}-spinning`]: sSpinning,
[`${prefixCls}-show-text`]: !!tip,
}
@ -143,7 +156,7 @@ export default {
}
const containerClassName = {
[`${prefixCls}-container`]: true,
[`${prefixCls}-blur`]: stateSpinning,
[`${prefixCls}-blur`]: sSpinning,
}
return (
@ -152,7 +165,7 @@ export default {
tag='div'
class={animateClassName}
>
{stateSpinning && <div key='loading'>{spinElement}</div>}
{sSpinning && <div key='loading'>{spinElement}</div>}
<div class={containerClassName} key='container'>
{children}
</div>

View File

@ -21,7 +21,7 @@ Use custom loading indicator.
export default {
data () {
return {
indicator: <i class="anticon anticon-loading anticon-spin ant-spin-dot" style="font-size: 24px;"></i>
indicator: <a-icon type="loading" style="font-size: 24px" spin />
}
},
}

View File

@ -10,6 +10,7 @@ The whole of the step bar.
| progressDot | Steps with progress dot style, customize the progress dot by setting a scoped slot. labelPlacement will be `vertical` | Boolean or slot="progressDot" slot-scope="{index, status, title, description, prefixCls})" | false |
| size | to specify the size of the step bar, `default` and `small` are currently supported | string | `default` |
| status | to specify the status of current step, can be set to one of the following values: `wait` `process` `finish` `error` | string | `process` |
| initial | set the initial step, counting from 0 | number | 0 |
### Steps.Step

View File

@ -1,13 +1,16 @@
import PropTypes from '../_util/vue-types'
import { initDefaultProps, getOptionProps, getComponentFromProp } from '../_util/props-util'
import { initDefaultProps, getOptionProps } from '../_util/props-util'
import VcSteps from '../vc-steps'
import Icon from '../icon'
const getStepsProps = (defaultProps = {}) => {
const props = {
prefixCls: PropTypes.string,
iconPrefix: PropTypes.string,
current: PropTypes.number,
initial: PropTypes.number,
labelPlacement: PropTypes.oneOf(['horizontal', 'vertical']),
status: PropTypes.oneOf(['wait', 'process', 'finish', 'error']),
size: PropTypes.oneOf(['default', 'small']),
direction: PropTypes.oneOf(['horizontal', 'vertical']),
@ -29,13 +32,15 @@ const Steps = {
Step: { ...VcSteps.Step, name: 'AStep' },
render () {
const props = getOptionProps(this)
const { prefixCls } = props
const icons = {
finish: <Icon type='check' class={`${prefixCls}-finish-icon`} />,
error: <Icon type='close' class={`${prefixCls}-error-icon`} />,
}
const stepsProps = {
props: {
icons,
...props,
icons: props.icons || {
error: getComponentFromProp(this, 'icons.error'),
finish: getComponentFromProp(this, 'icons.finish'),
},
},
on: this.$listeners,
scopedSlots: this.$scopedSlots,

View File

@ -11,6 +11,7 @@
| progressDot | 点状步骤条,可以设置为一个 作用域插槽,labelPlacement 将强制为`vertical` | Boolean or slot="progressDot" slot-scope="{index, status, title, description, prefixCls})" | false |
| size | 指定大小,目前支持普通(`default`)和迷你(`small` | string | default |
| status | 指定当前步骤的状态,可选 `wait` `process` `finish` `error` | string | process |
| initial | 起始序号,从 0 开始记数 | number | 0 |
### Steps.Step

View File

@ -17,7 +17,7 @@ With text and icon.
<br>
<a-switch defaultChecked >
<a-icon type="check" slot="checkedChildren"/>
<a-icon type="cross" slot="unCheckedChildren"/>
<a-icon type="close" slot="unCheckedChildren"/>
</a-switch>
</div>
</template>

View File

@ -3,6 +3,7 @@ import PropTypes from '../_util/vue-types'
import { getOptionProps, getComponentFromProp } from '../_util/props-util'
import VcSwitch from '../vc-switch'
import Wave from '../_util/wave'
import Icon from '../icon'
const Switch = {
name: 'ASwitch',
@ -38,10 +39,17 @@ const Switch = {
[`${prefixCls}-small`]: size === 'small',
[`${prefixCls}-loading`]: loading,
}
const loadingIcon = loading ? (
<Icon
type='loading'
class={`${prefixCls}-loading-icon`}
/>
) : null
const switchProps = {
props: {
...restProps,
prefixCls,
loadingIcon,
},
on: this.$listeners,
class: classes,

View File

@ -1,3 +1,4 @@
// base react-slick 0.23.2
import Slider from './slider'
export default Slider

View File

@ -3,7 +3,10 @@ import Tooltip from '../../vc-tooltip'
import '../assets/index.less'
import '../../vc-tooltip/assets/bootstrap.less'
const { Handle, Range } = Slider
const { Handle } = Slider
const { createSliderWithTooltip } = Slider
const Range = createSliderWithTooltip(Slider.Range)
export default {
data () {
@ -18,18 +21,16 @@ export default {
},
},
render () {
const handle = (h, props) => {
const { value, dragging, index, refStr, style, ...restProps } = props
const handle = (props) => {
const { value, dragging, index, ref, style, ...restProps } = props
const handleProps = {
props: {
...restProps,
value,
},
attrs: {
refStr,
},
key: index,
style,
ref,
}
return (
<Tooltip
@ -45,59 +46,60 @@ export default {
)
}
const handleRange = (h, { value, dragging, index, disabled, style, ...restProps }) => {
const tipFormatter = value => `${value}%`
const tipProps = {}
// const handleRange = (h, { value, ref, dragging, index, disabled, style, ...restProps }) => {
// const tipFormatter = value => `${value}%`
// const tipProps = {}
const {
prefixCls = 'rc-slider-tooltip',
overlay = tipFormatter(value),
placement = 'top',
visible = visible || false,
...restTooltipProps } = tipProps
// const {
// prefixCls = 'rc-slider-tooltip',
// overlay = tipFormatter(value),
// placement = 'top',
// visible = visible || false,
// ...restTooltipProps } = tipProps
let handleStyleWithIndex
if (Array.isArray(style)) {
handleStyleWithIndex = style[index] || style[0]
} else {
handleStyleWithIndex = style
}
// let handleStyleWithIndex
// if (Array.isArray(style)) {
// handleStyleWithIndex = style[index] || style[0]
// } else {
// handleStyleWithIndex = style
// }
const tooltipProps = {
props: {
prefixCls,
overlay,
placement,
visible: (!disabled && (this.visibles[index] || dragging)) || visible,
...restTooltipProps,
},
key: index,
}
const handleProps = {
props: {
value,
...restProps,
},
on: {
mouseenter: () => this.handleTooltipVisibleChange(index, true),
mouseleave: () => this.handleTooltipVisibleChange(index, false),
},
style: {
...handleStyleWithIndex,
},
}
// const tooltipProps = {
// props: {
// prefixCls,
// overlay,
// placement,
// visible: (!disabled && (this.visibles[index] || dragging)) || visible,
// ...restTooltipProps,
// },
// key: index,
// }
// const handleProps = {
// props: {
// value,
// ...restProps,
// },
// on: {
// mouseenter: () => this.handleTooltipVisibleChange(index, true),
// mouseleave: () => this.handleTooltipVisibleChange(index, false),
// },
// style: {
// ...handleStyleWithIndex,
// },
// ref,
// }
return (
<Tooltip
{...tooltipProps}
>
// return (
// <Tooltip
// {...tooltipProps}
// >
<Handle
{...handleProps}
/>
</Tooltip>
)
}
// <Handle
// {...handleProps}
// />
// </Tooltip>
// )
// }
const wrapperStyle = 'width: 400px; margin: 50px'
return (
@ -108,7 +110,7 @@ export default {
</div>
<div style={wrapperStyle}>
<p>Range with custom handle</p>
<Range min={0} max={20} defaultValue={[3, 10]} handle={handleRange} />
<Range min={0} max={20} defaultValue={[3, 10]} tipFormatter={value => `${value}%`} />
</div>
</div>
)

View File

@ -118,7 +118,7 @@ const Range = {
this.onChange({ bounds: nextBounds })
},
onEnd () {
this.setState({ sHandle: null }, this.onBlur)
this.setState({ sHandle: null }, this.blur)
this.removeDocumentEvents()
this.$emit('afterChange', this.bounds)
},
@ -210,7 +210,7 @@ const Range = {
nextHandle = nextBounds.indexOf(value)
}
this.onChange({
handle: nextHandle,
sHandle: nextHandle,
bounds: nextBounds,
})
if (isFromKeyboardEvent) {
@ -334,17 +334,17 @@ const Range = {
disabled,
min,
max,
handle: handleGenerator,
handle,
defaultHandle,
trackStyle,
handleStyle,
tabIndex,
$createElement,
} = this
const handleGenerator = handle || defaultHandle
const offsets = bounds.map(v => this.calcOffset(v))
const handleClassName = `${prefixCls}-handle`
const handles = bounds.map((v, i) => handleGenerator($createElement, {
const handles = bounds.map((v, i) => handleGenerator({
className: classNames({
[handleClassName]: true,
[`${handleClassName}-${i + 1}`]: true,

View File

@ -165,11 +165,13 @@ const Slider = {
tabIndex,
min,
max,
handle: handleGenerator,
handle,
defaultHandle,
} = this
const handleGenerator = handle || defaultHandle
const { sValue, dragging } = this
const offset = this.calcOffset(sValue)
const handle = handleGenerator(this.$createElement, {
const handles = handleGenerator({
className: `${prefixCls}-handle`,
prefixCls,
vertical,
@ -190,7 +192,7 @@ const Slider = {
const _trackStyle = trackStyle[0] || trackStyle
return {
tracks: this.getTrack({ prefixCls, vertical, included, offset, minimumTrackStyle, _trackStyle }),
handles: handle,
handles,
}
},
},

View File

@ -45,19 +45,19 @@ export default function createSlider (Component) {
max: 100,
step: 1,
marks: {},
handle (h, { index, ref, className, style, ...restProps }) {
delete restProps.dragging
const handleProps = {
props: {
...restProps,
},
class: className,
style,
key: index,
ref,
}
return <Handle {...handleProps} />
},
// handle ({ index, ref, className, style, ...restProps }) {
// delete restProps.dragging
// const handleProps = {
// props: {
// ...restProps,
// },
// class: className,
// style,
// key: index,
// ref,
// }
// return <Handle {...handleProps} />
// },
included: true,
disabled: false,
dots: false,
@ -106,6 +106,19 @@ export default function createSlider (Component) {
},
},
methods: {
defaultHandle ({ index, ref, className, style, ...restProps }) {
delete restProps.dragging
const handleProps = {
props: {
...restProps,
},
class: className,
style,
key: index,
ref,
}
return <Handle {...handleProps} />
},
onMouseDown (e) {
if (e.button !== 0) { return }
const isVertical = this.vertical

View File

@ -6,7 +6,7 @@ import Handle from './Handle'
export default function createSliderWithTooltip (Component) {
return {
mixins: [BaseMixin],
mixins: [BaseMixin, Component],
props: {
...Component.props,
tipFormatter: PropTypes.func.def((value) => { return value }),