add cascader
parent
de23e4de11
commit
6e8b5b9a20
|
@ -149,5 +149,6 @@ export {
|
||||||
getKey,
|
getKey,
|
||||||
getAttrs,
|
getAttrs,
|
||||||
getValueByProp,
|
getValueByProp,
|
||||||
|
parseStyleText,
|
||||||
}
|
}
|
||||||
export default hasProp
|
export default hasProp
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { filterEmpty } from './props-util'
|
import { filterEmpty, parseStyleText } from './props-util'
|
||||||
export function cloneVNode (vnode, deep) {
|
export function cloneVNode (vnode, deep) {
|
||||||
const componentOptions = vnode.componentOptions
|
const componentOptions = vnode.componentOptions
|
||||||
const data = vnode.data
|
const data = vnode.data
|
||||||
|
@ -62,18 +62,45 @@ export function cloneElement (n, nodeProps, deep) {
|
||||||
const node = cloneVNode(ele, deep)
|
const node = cloneVNode(ele, deep)
|
||||||
const { props = {}, key, on = {}, children } = nodeProps
|
const { props = {}, key, on = {}, children } = nodeProps
|
||||||
const data = node.data || {}
|
const data = node.data || {}
|
||||||
const { style = {},
|
let cls = {}
|
||||||
class: cls = {},
|
let style = {}
|
||||||
|
const {
|
||||||
attrs = {},
|
attrs = {},
|
||||||
ref,
|
ref,
|
||||||
domProps = {},
|
domProps = {},
|
||||||
|
style: tempStyle = {},
|
||||||
|
class: tempCls = {},
|
||||||
} = nodeProps
|
} = 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, {
|
node.data = Object.assign({}, data, {
|
||||||
style: { ...data.style, ...style },
|
style,
|
||||||
attrs: { ...data.attrs, ...attrs },
|
attrs: { ...data.attrs, ...attrs },
|
||||||
class: { ...data.class, ...cls },
|
class: cls,
|
||||||
domProps: { ...data.domProps, ...domProps },
|
domProps: { ...data.domProps, ...domProps },
|
||||||
})
|
})
|
||||||
|
|
||||||
if (node.componentOptions) {
|
if (node.componentOptions) {
|
||||||
node.componentOptions.propsData = node.componentOptions.propsData || {}
|
node.componentOptions.propsData = node.componentOptions.propsData || {}
|
||||||
node.componentOptions.listeners = node.componentOptions.listeners || {}
|
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 Affix } from './affix'
|
||||||
|
|
||||||
|
export { default as Cascader } from './cascader'
|
||||||
|
|
||||||
|
|
|
@ -25,3 +25,4 @@ import './select/style'
|
||||||
import './switch/style'
|
import './switch/style'
|
||||||
import './auto-complete/style'
|
import './auto-complete/style'
|
||||||
import './affix/style'
|
import './affix/style'
|
||||||
|
import './cascader/style'
|
||||||
|
|
|
@ -3,7 +3,7 @@ const AsyncComp = () => {
|
||||||
const hashs = window.location.hash.split('/')
|
const hashs = window.location.hash.split('/')
|
||||||
const d = hashs[hashs.length - 1]
|
const d = hashs[hashs.length - 1]
|
||||||
return {
|
return {
|
||||||
component: import(`../components/vc-cascader/demo/${d}`),
|
component: import(`../components/cascader/demo/${d}`),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export default [
|
export default [
|
||||||
|
|
Loading…
Reference in New Issue