add cascader
							parent
							
								
									de23e4de11
								
							
						
					
					
						commit
						6e8b5b9a20
					
				|  | @ -149,5 +149,6 @@ export { | |||
|   getKey, | ||||
|   getAttrs, | ||||
|   getValueByProp, | ||||
|   parseStyleText, | ||||
| } | ||||
| export default hasProp | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| import { filterEmpty } from './props-util' | ||||
| import { filterEmpty, parseStyleText } from './props-util' | ||||
| export function cloneVNode (vnode, deep) { | ||||
|   const componentOptions = vnode.componentOptions | ||||
|   const data = vnode.data | ||||
|  | @ -62,18 +62,45 @@ export function cloneElement (n, nodeProps, deep) { | |||
|   const node = cloneVNode(ele, deep) | ||||
|   const { props = {}, key, on = {}, children } = nodeProps | ||||
|   const data = node.data || {} | ||||
|   const { style = {}, | ||||
|     class: cls = {}, | ||||
|   let cls = {} | ||||
|   let style = {} | ||||
|   const { | ||||
|     attrs = {}, | ||||
|     ref, | ||||
|     domProps = {}, | ||||
|     style: tempStyle = {}, | ||||
|     class: tempCls = {}, | ||||
|   } = nodeProps | ||||
| 
 | ||||
|   if (typeof data.style === 'string') { | ||||
|     style = parseStyleText(data.style) | ||||
|   } else { | ||||
|     style = { ...data.style, ...style } | ||||
|   } | ||||
|   if (typeof tempStyle === 'string') { | ||||
|     style = { ...style, ...parseStyleText(style) } | ||||
|   } else { | ||||
|     style = { ...style, ...tempStyle } | ||||
|   } | ||||
| 
 | ||||
|   if (typeof data.class === 'string') { | ||||
|     cls[data.class] = true | ||||
|     data.class.split(' ').forEach(c => { cls[c.trim()] = true }) | ||||
|   } else { | ||||
|     cls = { ...data.class, ...cls } | ||||
|   } | ||||
|   if (typeof tempCls === 'string') { | ||||
|     tempCls.split(' ').forEach(c => { cls[c.trim()] = true }) | ||||
|   } else { | ||||
|     cls = { ...cls, ...tempCls } | ||||
|   } | ||||
|   node.data = Object.assign({}, data, { | ||||
|     style: { ...data.style, ...style }, | ||||
|     style, | ||||
|     attrs: { ...data.attrs, ...attrs }, | ||||
|     class: { ...data.class, ...cls }, | ||||
|     class: cls, | ||||
|     domProps: { ...data.domProps, ...domProps }, | ||||
|   }) | ||||
| 
 | ||||
|   if (node.componentOptions) { | ||||
|     node.componentOptions.propsData = node.componentOptions.propsData || {} | ||||
|     node.componentOptions.listeners = node.componentOptions.listeners || {} | ||||
|  |  | |||
|  | @ -0,0 +1,53 @@ | |||
| 
 | ||||
| <cn> | ||||
| #### 基本 | ||||
| 省市区级联。 | ||||
| </cn> | ||||
| 
 | ||||
| <us> | ||||
| #### Basic | ||||
| Cascade selection box for selecting province/city/district. | ||||
| </us> | ||||
| 
 | ||||
| ```html | ||||
| <template> | ||||
|   <a-cascader :options="options" @change="onChange" placeholder="Please select" /> | ||||
| </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> | ||||
| ``` | ||||
| 
 | ||||
|  | @ -0,0 +1,374 @@ | |||
| <script> | ||||
| import PropTypes from '../_util/vue-types' | ||||
| import VcCascader from '../vc-cascader' | ||||
| import arrayTreeFilter from 'array-tree-filter' | ||||
| import classNames from 'classnames' | ||||
| import omit from 'omit.js' | ||||
| import KeyCode from '../_util/KeyCode' | ||||
| import Input from '../input' | ||||
| import Icon from '../icon' | ||||
| import { hasProp, filterEmpty, getOptionProps } from '../_util/props-util' | ||||
| import BaseMixin from '../_util/BaseMixin' | ||||
| 
 | ||||
| const CascaderOptionType = PropTypes.shape({ | ||||
|   value: PropTypes.string.isRequired, | ||||
|   label: PropTypes.any.isRequired, | ||||
|   disabled: PropTypes.bool, | ||||
|   children: PropTypes.array, | ||||
|   __IS_FILTERED_OPTION: PropTypes.bool, | ||||
| }).loose | ||||
| 
 | ||||
| const CascaderExpandTrigger = PropTypes.oneOf(['click', 'hover']) | ||||
| 
 | ||||
| const ShowSearchType = PropTypes.shape({ | ||||
|   filter: PropTypes.func, | ||||
|   render: PropTypes.func, | ||||
|   sort: PropTypes.func, | ||||
|   matchInputWidth: PropTypes.bool, | ||||
| }).loose | ||||
| function noop () {} | ||||
| 
 | ||||
| const CascaderProps = { | ||||
|   /** 可选项数据源 */ | ||||
|   options: PropTypes.arrayOf(CascaderOptionType).def([]), | ||||
|   /** 默认的选中项 */ | ||||
|   defaultValue: PropTypes.arrayOf(PropTypes.string), | ||||
|   /** 指定选中项 */ | ||||
|   value: PropTypes.arrayOf(PropTypes.string), | ||||
|   /** 选择完成后的回调 */ | ||||
|   // onChange?: (value: string[], selectedOptions?: CascaderOptionType[]) => void; | ||||
|   /** 选择后展示的渲染函数 */ | ||||
|   displayRender: PropTypes.func, | ||||
|   transitionName: PropTypes.string.def('slide-up'), | ||||
|   popupStyle: PropTypes.object.def({}), | ||||
|   /** 自定义浮层类名 */ | ||||
|   popupClassName: PropTypes.string, | ||||
|   /** 浮层预设位置:`bottomLeft` `bottomRight` `topLeft` `topRight` */ | ||||
|   popupPlacement: PropTypes.oneOf(['bottomLeft', 'bottomRight', 'topLeft', 'topRight']).def('bottomLeft'), | ||||
|   /** 输入框占位文本*/ | ||||
|   placeholder: PropTypes.string.def('Please select'), | ||||
|   /** 输入框大小,可选 `large` `default` `small` */ | ||||
|   size: PropTypes.oneOf(['large', 'default', 'small']), | ||||
|   /** 禁用*/ | ||||
|   disabled: PropTypes.bool.def(false), | ||||
|   /** 是否支持清除*/ | ||||
|   allowClear: PropTypes.bool.def(true), | ||||
|   showSearch: PropTypes.oneOfType([PropTypes.bool, ShowSearchType]), | ||||
|   notFoundContent: PropTypes.any.def('Not Found'), | ||||
|   loadData: PropTypes.func, | ||||
|   /** 次级菜单的展开方式,可选 'click' 和 'hover' */ | ||||
|   expandTrigger: CascaderExpandTrigger, | ||||
|   /** 当此项为 true 时,点选每级菜单选项值都会发生变化 */ | ||||
|   changeOnSelect: PropTypes.bool, | ||||
|   /** 浮层可见变化时回调 */ | ||||
|   // onPopupVisibleChange?: (popupVisible: boolean) => void; | ||||
|   prefixCls: PropTypes.string.def('ant-cascader'), | ||||
|   inputPrefixCls: PropTypes.string.def('ant-input'), | ||||
|   getPopupContainer: PropTypes.func, | ||||
|   popupVisible: PropTypes.bool, | ||||
| } | ||||
| 
 | ||||
| function defaultFilterOption (inputValue, path) { | ||||
|   return path.some(option => option.label.indexOf(inputValue) > -1) | ||||
| } | ||||
| 
 | ||||
| function defaultSortFilteredOption (a, b, inputValue) { | ||||
|   function callback (elem) { | ||||
|     return elem.label.indexOf(inputValue) > -1 | ||||
|   } | ||||
| 
 | ||||
|   return a.findIndex(callback) - b.findIndex(callback) | ||||
| } | ||||
| 
 | ||||
| const defaultDisplayRender = (label) => label.join(' / ') | ||||
| 
 | ||||
| export default { | ||||
|   mixins: [BaseMixin], | ||||
|   props: CascaderProps, | ||||
|   data () { | ||||
|     this.cachedOptions = [] | ||||
|     const { value, defaultValue, popupVisible, showSearch, options, changeOnSelect, flattenTree } = this | ||||
|     return { | ||||
|       sValue: value || defaultValue || [], | ||||
|       inputValue: '', | ||||
|       inputFocused: false, | ||||
|       sPopupVisible: popupVisible, | ||||
|       flattenOptions: showSearch && flattenTree(options, changeOnSelect), | ||||
|     } | ||||
|   }, | ||||
|   watch: { | ||||
|     value (val) { | ||||
|       this.setState({ sValue: val || [] }) | ||||
|     }, | ||||
|     popupVisible (val) { | ||||
|       this.setState({ sPopupVisible: val }) | ||||
|     }, | ||||
|     options (val) { | ||||
|       if (this.showSearch) { | ||||
|         this.setState({ flattenOptions: this.flattenTree(this.options, this.changeOnSelect) }) | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|   methods: { | ||||
|     highlightKeyword (str, keyword, prefixCls) { | ||||
|       return str.split(keyword) | ||||
|         .map((node, index) => index === 0 ? node : [ | ||||
|           <span class={`${prefixCls}-menu-item-keyword`} key='seperator'>{keyword}</span>, | ||||
|           node, | ||||
|         ]) | ||||
|     }, | ||||
| 
 | ||||
|     defaultRenderFilteredOption (inputValue, path, prefixCls) { | ||||
|       return path.map(({ label }, index) => { | ||||
|         const node = label.indexOf(inputValue) > -1 | ||||
|           ? this.highlightKeyword(label, inputValue, prefixCls) : label | ||||
|         return index === 0 ? node : [' / ', node] | ||||
|       }) | ||||
|     }, | ||||
|     handleChange (value, selectedOptions) { | ||||
|       this.setState({ inputValue: '' }) | ||||
|       if (selectedOptions[0].__IS_FILTERED_OPTION) { | ||||
|         const unwrappedValue = value[0] | ||||
|         const unwrappedSelectedOptions = selectedOptions[0].path | ||||
|         this.setValue(unwrappedValue, unwrappedSelectedOptions) | ||||
|         return | ||||
|       } | ||||
|       this.setValue(value, selectedOptions) | ||||
|     }, | ||||
| 
 | ||||
|     handlePopupVisibleChange (popupVisible) { | ||||
|       if (!hasProp(this, 'popupVisible')) { | ||||
|         this.setState({ | ||||
|           sPopupVisible: popupVisible, | ||||
|           inputFocused: popupVisible, | ||||
|           inputValue: popupVisible ? this.inputValue : '', | ||||
|         }) | ||||
|       } | ||||
|       this.$emit('popupVisibleChange', popupVisible) | ||||
|     }, | ||||
| 
 | ||||
|     handleInputBlur () { | ||||
|       this.setState({ | ||||
|         inputFocused: false, | ||||
|       }) | ||||
|     }, | ||||
| 
 | ||||
|     handleInputClick (e) { | ||||
|       const { inputFocused, sPopupVisible } = this | ||||
|       // Prevent `Trigger` behaviour. | ||||
|       if (inputFocused || sPopupVisible) { | ||||
|         e.stopPropagation() | ||||
|         e.nativeEvent.stopImmediatePropagation() | ||||
|       } | ||||
|     }, | ||||
| 
 | ||||
|     handleKeyDown (e) { | ||||
|       if (e.keyCode === KeyCode.BACKSPACE) { | ||||
|         e.stopPropagation() | ||||
|       } | ||||
|     }, | ||||
| 
 | ||||
|     handleInputChange (e) { | ||||
|       const inputValue = e.target.value | ||||
|       this.setState({ inputValue }) | ||||
|     }, | ||||
| 
 | ||||
|     setValue (value, selectedOptions) { | ||||
|       if (!hasProp(this, 'value')) { | ||||
|         this.setState({ sValue: value }) | ||||
|       } | ||||
|       this.$emit('change', value, selectedOptions) | ||||
|     }, | ||||
| 
 | ||||
|     getLabel () { | ||||
|       const { options, displayRender = defaultDisplayRender } = this | ||||
|       const value = this.sValue | ||||
|       const unwrappedValue = Array.isArray(value[0]) ? value[0] : value | ||||
|       const selectedOptions = arrayTreeFilter(options, | ||||
|         (o, level) => o.value === unwrappedValue[level], | ||||
|       ) | ||||
|       const label = selectedOptions.map(o => o.label) | ||||
|       return displayRender(label, selectedOptions) | ||||
|     }, | ||||
| 
 | ||||
|     clearSelection (e) { | ||||
|       e.preventDefault() | ||||
|       e.stopPropagation() | ||||
|       if (!this.inputValue) { | ||||
|         this.setValue([]) | ||||
|         this.handlePopupVisibleChange(false) | ||||
|       } else { | ||||
|         this.setState({ inputValue: '' }) | ||||
|       } | ||||
|     }, | ||||
| 
 | ||||
|     flattenTree (options, changeOnSelect, ancestor = []) { | ||||
|       let flattenOptions = [] | ||||
|       options.forEach((option) => { | ||||
|         const path = ancestor.concat(option) | ||||
|         if (changeOnSelect || !option.children || !option.children.length) { | ||||
|           flattenOptions.push(path) | ||||
|         } | ||||
|         if (option.children) { | ||||
|           flattenOptions = flattenOptions.concat(this.flattenTree(option.children, changeOnSelect, path)) | ||||
|         } | ||||
|       }) | ||||
|       return flattenOptions | ||||
|     }, | ||||
| 
 | ||||
|     generateFilteredOptions (prefixCls) { | ||||
|       const { showSearch, notFoundContent, flattenOptions, inputValue } = this | ||||
|       const { | ||||
|         filter = defaultFilterOption, | ||||
|         render = this.defaultRenderFilteredOption, | ||||
|         sort = defaultSortFilteredOption, | ||||
|       } = showSearch | ||||
|       const filtered = flattenOptions.filter((path) => filter(inputValue, path)) | ||||
|         .sort((a, b) => sort(a, b, inputValue)) | ||||
| 
 | ||||
|       if (filtered.length > 0) { | ||||
|         return filtered.map((path) => { | ||||
|           return { | ||||
|             __IS_FILTERED_OPTION: true, | ||||
|             path, | ||||
|             label: render(inputValue, path, prefixCls), | ||||
|             value: path.map((o) => o.value), | ||||
|             disabled: path.some((o) => o.disabled), | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|       return [{ label: notFoundContent, value: 'ANT_CASCADER_NOT_FOUND', disabled: true }] | ||||
|     }, | ||||
| 
 | ||||
|     focus () { | ||||
|       this.$refs.input.focus() | ||||
|     }, | ||||
| 
 | ||||
|     blur () { | ||||
|       this.$refs.input.blur() | ||||
|     }, | ||||
|   }, | ||||
| 
 | ||||
|   render () { | ||||
|     const { $slots, sValue: value, sPopupVisible, inputValue } = this | ||||
|     const props = getOptionProps(this) | ||||
|     const { | ||||
|       prefixCls, inputPrefixCls, placeholder, size, disabled, | ||||
|       allowClear, showSearch = false, ...otherProps } = props | ||||
| 
 | ||||
|     const sizeCls = classNames({ | ||||
|       [`${inputPrefixCls}-lg`]: size === 'large', | ||||
|       [`${inputPrefixCls}-sm`]: size === 'small', | ||||
|     }) | ||||
|     const clearIcon = (allowClear && !disabled && value.length > 0) || inputValue ? ( | ||||
|       <Icon | ||||
|         type='cross-circle' | ||||
|         class={`${prefixCls}-picker-clear`} | ||||
|         onClick={this.clearSelection} | ||||
|       /> | ||||
|     ) : null | ||||
|     const arrowCls = classNames({ | ||||
|       [`${prefixCls}-picker-arrow`]: true, | ||||
|       [`${prefixCls}-picker-arrow-expand`]: sPopupVisible, | ||||
|     }) | ||||
|     const pickerCls = classNames( | ||||
|       `${prefixCls}-picker`, { | ||||
|         [`${prefixCls}-picker-with-value`]: inputValue, | ||||
|         [`${prefixCls}-picker-disabled`]: disabled, | ||||
|         [`${prefixCls}-picker-${size}`]: !!size, | ||||
|       }) | ||||
| 
 | ||||
|     // Fix bug of https://github.com/facebook/react/pull/5004 | ||||
|     // and https://fb.me/react-unknown-prop | ||||
|     const tempInputProps = omit(otherProps, [ | ||||
|       'options', | ||||
|       'popupPlacement', | ||||
|       'transitionName', | ||||
|       'displayRender', | ||||
|       'changeOnSelect', | ||||
|       'expandTrigger', | ||||
|       'popupVisible', | ||||
|       'getPopupContainer', | ||||
|       'loadData', | ||||
|       'popupClassName', | ||||
|       'filterOption', | ||||
|       'renderFilteredOption', | ||||
|       'sortFilteredOption', | ||||
|       'notFoundContent', | ||||
|     ]) | ||||
| 
 | ||||
|     let options = this.options | ||||
|     if (inputValue) { | ||||
|       options = this.generateFilteredOptions(prefixCls) | ||||
|     } | ||||
|     // Dropdown menu should keep previous status until it is fully closed. | ||||
|     if (!sPopupVisible) { | ||||
|       options = this.cachedOptions | ||||
|     } else { | ||||
|       this.cachedOptions = options | ||||
|     } | ||||
| 
 | ||||
|     const dropdownMenuColumnStyle = {} | ||||
|     const isNotFound = (options || []).length === 1 && options[0].value === 'ANT_CASCADER_NOT_FOUND' | ||||
|     if (isNotFound) { | ||||
|       dropdownMenuColumnStyle.height = 'auto' // Height of one row. | ||||
|     } | ||||
|     // The default value of `matchInputWidth` is `true` | ||||
|     const resultListMatchInputWidth = showSearch.matchInputWidth !== false | ||||
|     if (resultListMatchInputWidth && inputValue && this.input) { | ||||
|       dropdownMenuColumnStyle.width = this.input.input.offsetWidth | ||||
|     } | ||||
|     const inputProps = { | ||||
|       props: { | ||||
|         ...tempInputProps, | ||||
|         prefixCls: inputPrefixCls, | ||||
|         placeholder: value && value.length > 0 ? undefined : placeholder, | ||||
|         value: inputValue, | ||||
|         disabled: disabled, | ||||
|         readOnly: !showSearch, | ||||
|         autoComplete: 'off', | ||||
|       }, | ||||
|       class: `${prefixCls}-input ${sizeCls}`, | ||||
|       ref: 'input', | ||||
|       on: { | ||||
|         click: showSearch ? this.handleInputClick : noop, | ||||
|         blur: showSearch ? this.handleInputBlur : noop, | ||||
|         keydown: this.handleKeyDown, | ||||
|         change: showSearch ? this.handleInputChange : noop, | ||||
|       }, | ||||
|     } | ||||
|     const children = filterEmpty($slots.default) | ||||
|     const input = children.length ? children : ( | ||||
|       <span | ||||
|         class={pickerCls} | ||||
|       > | ||||
|         <span class={`${prefixCls}-picker-label`}> | ||||
|           {this.getLabel()} | ||||
|         </span> | ||||
|         <Input {...inputProps}/> | ||||
|         {clearIcon} | ||||
|         <Icon type='down' class={arrowCls} /> | ||||
|       </span> | ||||
|     ) | ||||
|     const cascaderProps = { | ||||
|       props: { | ||||
|         ...props, | ||||
|         options: options, | ||||
|         value: value, | ||||
|         popupVisible: sPopupVisible, | ||||
|         dropdownMenuColumnStyle: dropdownMenuColumnStyle, | ||||
|       }, | ||||
|       on: { | ||||
|         popupVisibleChange: this.handlePopupVisibleChange, | ||||
|         change: this.handleChange, | ||||
|       }, | ||||
|     } | ||||
|     return ( | ||||
|       <VcCascader {...cascaderProps}> | ||||
|         {input} | ||||
|       </VcCascader> | ||||
|     ) | ||||
|   }, | ||||
| } | ||||
| 
 | ||||
| </script> | ||||
|  | @ -0,0 +1,5 @@ | |||
| import '../../style/index.less' | ||||
| import './index.less' | ||||
| 
 | ||||
| // style dependencies
 | ||||
| import '../../input/style' | ||||
|  | @ -0,0 +1,214 @@ | |||
| @import "../../style/themes/default"; | ||||
| @import "../../style/mixins/index"; | ||||
| @import "../../input/style/mixin"; | ||||
| 
 | ||||
| @cascader-prefix-cls: ~"@{ant-prefix}-cascader"; | ||||
| 
 | ||||
| .@{cascader-prefix-cls} { | ||||
|   .reset-component; | ||||
| 
 | ||||
|   &-input.@{ant-prefix}-input { | ||||
|     // Add important to fix https://github.com/ant-design/ant-design/issues/5078 | ||||
|     // because input.less will compile after cascader.less | ||||
|     background-color: transparent !important; | ||||
|     cursor: pointer; | ||||
|     width: 100%; | ||||
|     display: block; | ||||
|   } | ||||
| 
 | ||||
|   &-picker { | ||||
|     .reset-component; | ||||
|     position: relative; | ||||
|     display: inline-block; | ||||
|     cursor: pointer; | ||||
|     background-color: @component-background; | ||||
|     border-radius: @border-radius-base; | ||||
|     outline: 0; | ||||
| 
 | ||||
|     &-with-value &-label { | ||||
|       color: transparent; | ||||
|     } | ||||
| 
 | ||||
|     &-disabled { | ||||
|       cursor: not-allowed; | ||||
|       background: @input-disabled-bg; | ||||
|       color: @disabled-color; | ||||
|       .@{cascader-prefix-cls}-input { | ||||
|         cursor: not-allowed; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     &:focus .@{cascader-prefix-cls}-input { | ||||
|       .active; | ||||
|     } | ||||
| 
 | ||||
|     &-label { | ||||
|       position: absolute; | ||||
|       left: 0; | ||||
|       height: 20px; | ||||
|       line-height: 20px; | ||||
|       top: 50%; | ||||
|       margin-top: -10px; | ||||
|       white-space: nowrap; | ||||
|       text-overflow: ellipsis; | ||||
|       overflow: hidden; | ||||
|       width: 100%; | ||||
|       padding: 0 @control-padding-horizontal; | ||||
|     } | ||||
| 
 | ||||
|     &-clear { | ||||
|       opacity: 0; | ||||
|       position: absolute; | ||||
|       right: @control-padding-horizontal; | ||||
|       z-index: 2; | ||||
|       background: @component-background; | ||||
|       top: 50%; | ||||
|       font-size: @font-size-sm; | ||||
|       color: @disabled-color; | ||||
|       width: 12px; | ||||
|       height: 12px; | ||||
|       margin-top: -6px; | ||||
|       line-height: 12px; | ||||
|       cursor: pointer; | ||||
|       transition: color 0.3s ease, opacity 0.15s ease; | ||||
|       &:hover { | ||||
|         color: @text-color-secondary; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     &:hover &-clear { | ||||
|       opacity: 1; | ||||
|     } | ||||
| 
 | ||||
|     // arrow | ||||
|     &-arrow { | ||||
|       position: absolute; | ||||
|       z-index: 1; | ||||
|       top: 50%; | ||||
|       right: @control-padding-horizontal; | ||||
|       width: 12px; | ||||
|       height: 12px; | ||||
|       font-size: 12px; | ||||
|       margin-top: -6px; | ||||
|       line-height: 12px; | ||||
|       color: @disabled-color; | ||||
|       &:before { | ||||
|         transition: transform .2s; | ||||
|       } | ||||
|       &&-expand { | ||||
|         &:before { | ||||
|           transform: rotate(180deg); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   &-picker-small &-picker-clear, | ||||
|   &-picker-small &-picker-arrow { | ||||
|     right: @control-padding-horizontal-sm; | ||||
|   } | ||||
| 
 | ||||
|   &-menus { | ||||
|     font-size: @font-size-base; | ||||
|     background: @component-background; | ||||
|     position: absolute; | ||||
|     z-index: @zindex-dropdown; | ||||
|     border-radius: @border-radius-base; | ||||
|     box-shadow: @box-shadow-base; | ||||
|     white-space: nowrap; | ||||
| 
 | ||||
|     ul, | ||||
|     ol { | ||||
|       list-style: none; | ||||
|       margin: 0; | ||||
|       padding: 0; | ||||
|     } | ||||
| 
 | ||||
|     &-empty, | ||||
|     &-hidden { | ||||
|       display: none; | ||||
|     } | ||||
|     &.slide-up-enter.slide-up-enter-active&-placement-bottomLeft, | ||||
|     &.slide-up-appear.slide-up-appear-active&-placement-bottomLeft { | ||||
|       animation-name: antSlideUpIn; | ||||
|     } | ||||
| 
 | ||||
|     &.slide-up-enter.slide-up-enter-active&-placement-topLeft, | ||||
|     &.slide-up-appear.slide-up-appear-active&-placement-topLeft { | ||||
|       animation-name: antSlideDownIn; | ||||
|     } | ||||
| 
 | ||||
|     &.slide-up-leave.slide-up-leave-active&-placement-bottomLeft { | ||||
|       animation-name: antSlideUpOut; | ||||
|     } | ||||
| 
 | ||||
|     &.slide-up-leave.slide-up-leave-active&-placement-topLeft { | ||||
|       animation-name: antSlideDownOut; | ||||
|     } | ||||
|   } | ||||
|   &-menu { | ||||
|     display: inline-block; | ||||
|     vertical-align: top; | ||||
|     min-width: 111px; | ||||
|     height: 180px; | ||||
|     list-style: none; | ||||
|     margin: 0; | ||||
|     padding: 0; | ||||
|     border-right: @border-width-base @border-style-base @border-color-split; | ||||
|     overflow: auto; | ||||
|     &:first-child { | ||||
|       border-radius: @border-radius-base 0 0 @border-radius-base; | ||||
|     } | ||||
|     &:last-child { | ||||
|       border-right-color: transparent; | ||||
|       margin-right: -1px; | ||||
|       border-radius: 0 @border-radius-base @border-radius-base 0; | ||||
|     } | ||||
|     &:only-child { | ||||
|       border-radius: @border-radius-base; | ||||
|     } | ||||
|   } | ||||
|   &-menu-item { | ||||
|     padding: 5px @control-padding-horizontal; | ||||
|     line-height: 22px; | ||||
|     cursor: pointer; | ||||
|     white-space: nowrap; | ||||
|     transition: all 0.3s; | ||||
|     &:hover { | ||||
|       background: @item-hover-bg; | ||||
|     } | ||||
|     &-disabled { | ||||
|       cursor: not-allowed; | ||||
|       color: @disabled-color; | ||||
|       &:hover { | ||||
|         background: transparent; | ||||
|       } | ||||
|     } | ||||
|     &-active:not(&-disabled) { | ||||
|       &, | ||||
|       &:hover { | ||||
|         background: @background-color-base; | ||||
|         font-weight: 600; | ||||
|       } | ||||
|     } | ||||
|     &-expand { | ||||
|       position: relative; | ||||
|       padding-right: 24px; | ||||
|       &:after { | ||||
|         .iconfont-font("\e61f"); | ||||
|         .iconfont-size-under-12px(8px); | ||||
|         color: @text-color-secondary; | ||||
|         position: absolute; | ||||
|         right: @control-padding-horizontal; | ||||
|       } | ||||
|     } | ||||
|     &-loading:after { | ||||
|       .iconfont-font("\e64d"); | ||||
|       animation: loadingCircle 1s infinite linear; | ||||
|     } | ||||
| 
 | ||||
|     & &-keyword { | ||||
|       color: @highlight-color; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -91,3 +91,5 @@ export { default as AutoComplete } from './auto-complete' | |||
| 
 | ||||
| export { default as Affix } from './affix' | ||||
| 
 | ||||
| export { default as Cascader } from './cascader' | ||||
| 
 | ||||
|  |  | |||
|  | @ -25,3 +25,4 @@ import './select/style' | |||
| import './switch/style' | ||||
| import './auto-complete/style' | ||||
| import './affix/style' | ||||
| import './cascader/style' | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ const AsyncComp = () => { | |||
|   const hashs = window.location.hash.split('/') | ||||
|   const d = hashs[hashs.length - 1] | ||||
|   return { | ||||
|     component: import(`../components/vc-cascader/demo/${d}`), | ||||
|     component: import(`../components/cascader/demo/${d}`), | ||||
|   } | ||||
| } | ||||
| export default [ | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 tjz
						tjz