add affix demo
parent
e59f61b63c
commit
10764b705b
|
@ -0,0 +1,23 @@
|
||||||
|
<cn>
|
||||||
|
#### 基本
|
||||||
|
最简单的用法。
|
||||||
|
</cn>
|
||||||
|
|
||||||
|
<us>
|
||||||
|
#### basic
|
||||||
|
The simplest usage.
|
||||||
|
</us>
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<a-affix>
|
||||||
|
<a-button type="primary">Affix top</a-button>
|
||||||
|
</a-affix>
|
||||||
|
<br />
|
||||||
|
<a-affix :offsetBottom="0">
|
||||||
|
<a-button type="primary">Affix bottom</a-button>
|
||||||
|
</a-affix>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
```
|
|
@ -0,0 +1,37 @@
|
||||||
|
<script>
|
||||||
|
import Basic from './basic'
|
||||||
|
import Onchange from './on-change'
|
||||||
|
import Target from './target'
|
||||||
|
import CN from '../index.zh-CN.md'
|
||||||
|
import US from '../index.en-US.md'
|
||||||
|
const md = {
|
||||||
|
cn: `# Affix 固钉
|
||||||
|
将页面元素钉在可视范围。
|
||||||
|
## 何时使用
|
||||||
|
当内容区域比较长,需要滚动页面时,这部分内容对应的操作或者导航需要在滚动范围内始终展现。常用于侧边菜单和按钮组合。
|
||||||
|
页面可视范围过小时,慎用此功能以免遮挡页面内容。
|
||||||
|
## 代码演示`,
|
||||||
|
us: `# Affix
|
||||||
|
Make an element stick to viewport.
|
||||||
|
## When To Use
|
||||||
|
When user browses a long web page, some content need to stick to the viewport. This is common for menus and actions.
|
||||||
|
Please note that Affix should not cover other content on the page, especially when the size of the viewport is small.
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
render () {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<md cn={md.cn} us={md.us}/>
|
||||||
|
<Basic />
|
||||||
|
<Onchange />
|
||||||
|
<Target />
|
||||||
|
<api>
|
||||||
|
<CN slot='cn' />
|
||||||
|
<US/>
|
||||||
|
</api>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,26 @@
|
||||||
|
<cn>
|
||||||
|
#### 固定状态改变的回调
|
||||||
|
可以获得是否固定的状态。
|
||||||
|
</cn>
|
||||||
|
|
||||||
|
<us>
|
||||||
|
#### Callback
|
||||||
|
Callback with affixed state.
|
||||||
|
</us>
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<a-affix :offsetTop="120" @change="change">
|
||||||
|
<a-button>120px to affix top</a-button>
|
||||||
|
</a-affix>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
change(affixed) {
|
||||||
|
console.log(affixed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
|
@ -0,0 +1,34 @@
|
||||||
|
<cn>
|
||||||
|
#### 滚动容器
|
||||||
|
用 `target` 设置 `Affix` 需要监听其滚动事件的元素,默认为 `window`。
|
||||||
|
</cn>
|
||||||
|
|
||||||
|
<us>
|
||||||
|
#### Container to scroll.
|
||||||
|
Set a `target` for 'Affix', which is listen to scroll event of target element (default is `window`).
|
||||||
|
</us>
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<div id="components-affix-demo-target" class="scrollable-container" ref="container">
|
||||||
|
<div class="background">
|
||||||
|
<a-affix :target="() => this.$refs.container">
|
||||||
|
<a-button type="primary">
|
||||||
|
Fixed at the top of container
|
||||||
|
</a-button>
|
||||||
|
</a-affix>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<style>
|
||||||
|
#components-affix-demo-target.scrollable-container {
|
||||||
|
height: 100px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
#components-affix-demo-target .background {
|
||||||
|
padding-top: 60px;
|
||||||
|
height: 300px;
|
||||||
|
background-image: url('https://zos.alipayobjects.com/rmsportal/RmjwQiJorKyobvI.jpg');
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
```
|
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
| Property | Description | Type | Default |
|
||||||
|
| -------- | ----------- | ---- | ------- |
|
||||||
|
| offsetBottom | Pixels to offset from bottom when calculating position of scroll | number | - |
|
||||||
|
| offsetTop | Pixels to offset from top when calculating position of scroll | number | 0 |
|
||||||
|
| target | specifies the scrollable area dom node | () => HTMLElement | () => window |
|
||||||
|
|
||||||
|
### events
|
||||||
|
| Events Name | Description | Arguments |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| onChange | Callback for when affix state is changed | Function(affixed) |
|
||||||
|
|
||||||
|
**Note:** Children of `Affix` can not be `position: absolute`, but you can set `Affix` as `position: absolute`:
|
||||||
|
|
||||||
|
````html
|
||||||
|
<a-affix :style="{ position: 'absolute', top: y, left: x}">
|
||||||
|
...
|
||||||
|
</a-affix>
|
||||||
|
````
|
|
@ -5,7 +5,8 @@ import classNames from 'classnames'
|
||||||
import shallowequal from 'shallowequal'
|
import shallowequal from 'shallowequal'
|
||||||
import omit from 'omit.js'
|
import omit from 'omit.js'
|
||||||
import getScroll from '../_util/getScroll'
|
import getScroll from '../_util/getScroll'
|
||||||
import { throttleByAnimationFrameDecorator } from '../_util/throttleByAnimationFrame'
|
import BaseMixin from '../_util/BaseMixin'
|
||||||
|
import throttleByAnimationFrame from '../_util/throttleByAnimationFrame'
|
||||||
|
|
||||||
function getTargetRect (target) {
|
function getTargetRect (target) {
|
||||||
return target !== window
|
return target !== window
|
||||||
|
@ -55,14 +56,10 @@ const AffixProps = {
|
||||||
prefixCls: PropTypes.string,
|
prefixCls: PropTypes.string,
|
||||||
}
|
}
|
||||||
|
|
||||||
// export interface AffixState {
|
|
||||||
// affixStyle: React.CSSProperties | undefined;
|
|
||||||
// placeholderStyle: React.CSSProperties | undefined;
|
|
||||||
// }
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Affix',
|
name: 'Affix',
|
||||||
props: AffixProps,
|
props: AffixProps,
|
||||||
|
mixins: [BaseMixin],
|
||||||
data () {
|
data () {
|
||||||
this.events = [
|
this.events = [
|
||||||
'resize',
|
'resize',
|
||||||
|
@ -79,6 +76,9 @@ export default {
|
||||||
placeholderStyle: undefined,
|
placeholderStyle: undefined,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
beforeMount () {
|
||||||
|
this.updatePosition = throttleByAnimationFrame(this.updatePosition)
|
||||||
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
const target = this.target || getDefaultTarget
|
const target = this.target || getDefaultTarget
|
||||||
// Wait for parent component ref has its value
|
// Wait for parent component ref has its value
|
||||||
|
@ -96,7 +96,6 @@ export default {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeDestroy () {
|
beforeDestroy () {
|
||||||
this.clearEventListeners()
|
this.clearEventListeners()
|
||||||
clearTimeout(this.timeout)
|
clearTimeout(this.timeout)
|
||||||
|
@ -130,7 +129,6 @@ export default {
|
||||||
this.setState({ placeholderStyle: placeholderStyle })
|
this.setState({ placeholderStyle: placeholderStyle })
|
||||||
},
|
},
|
||||||
|
|
||||||
// @throttleByAnimationFrameDecorator()
|
|
||||||
updatePosition (e) {
|
updatePosition (e) {
|
||||||
let { offsetTop } = this
|
let { offsetTop } = this
|
||||||
const { offsetBottom, offset, target = getDefaultTarget } = this
|
const { offsetBottom, offset, target = getDefaultTarget } = this
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
| 成员 | 说明 | 类型 | 默认值 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| offsetBottom | 距离窗口底部达到指定偏移量后触发 | number | |
|
||||||
|
| offsetTop | 距离窗口顶部达到指定偏移量后触发 | number | |
|
||||||
|
| target | 设置 `Affix` 需要监听其滚动事件的元素,值为一个返回对应 DOM 元素的函数 | () => HTMLElement | () => window |
|
||||||
|
|
||||||
|
|
||||||
|
### 事件
|
||||||
|
| 事件名称 | 说明 | 回调参数 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| change | 固定状态改变时触发的回调函数 | Function(affixed) |
|
||||||
|
|
||||||
|
|
||||||
|
**注意:**`Affix` 内的元素不要使用绝对定位,如需要绝对定位的效果,可以直接设置 `Affix` 为绝对定位:
|
||||||
|
|
||||||
|
````html
|
||||||
|
<a-affix :style="{ position: 'absolute', top: y, left: x}">
|
||||||
|
...
|
||||||
|
</a-affix>
|
||||||
|
````
|
|
@ -11,7 +11,7 @@ There are `primary` button, `default` button, `dashed` button and `danger` butto
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<template>
|
<template>
|
||||||
<div class='test'>
|
<div>
|
||||||
<a-button type="primary">Primary</a-button>
|
<a-button type="primary">Primary</a-button>
|
||||||
<a-button>Default</a-button>
|
<a-button>Default</a-button>
|
||||||
<a-button type="dashed">Dashed</a-button>
|
<a-button type="dashed">Dashed</a-button>
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
<script>
|
<script>
|
||||||
import { Tabs } from 'antd'
|
import { Tabs } from 'antd'
|
||||||
import omit from 'omit.js'
|
|
||||||
import PropTypes from '../_util/vue-types'
|
import PropTypes from '../_util/vue-types'
|
||||||
import addEventListener from '../_util/Dom/addEventListener'
|
import addEventListener from '../_util/Dom/addEventListener'
|
||||||
import { hasProp, getComponentFromProp, getComponentName } from '../_util/props-util'
|
import { getComponentFromProp, getComponentName } from '../_util/props-util'
|
||||||
import throttleByAnimationFrame from '../_util/throttleByAnimationFrame'
|
import throttleByAnimationFrame from '../_util/throttleByAnimationFrame'
|
||||||
import BaseMixin from '../_util/BaseMixin'
|
import BaseMixin from '../_util/BaseMixin'
|
||||||
|
|
||||||
|
@ -18,32 +17,25 @@
|
||||||
bordered: PropTypes.bool.def(true),
|
bordered: PropTypes.bool.def(true),
|
||||||
bodyStyle: PropTypes.object,
|
bodyStyle: PropTypes.object,
|
||||||
loading: PropTypes.bool.def(false),
|
loading: PropTypes.bool.def(false),
|
||||||
noHovering: PropTypes.bool.def(false),
|
|
||||||
hoverable: PropTypes.bool.def(false),
|
hoverable: PropTypes.bool.def(false),
|
||||||
type: PropTypes.string,
|
type: PropTypes.string,
|
||||||
actions: PropTypes.any,
|
actions: PropTypes.any,
|
||||||
tabList: PropTypes.array,
|
tabList: PropTypes.array,
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
|
this.updateWiderPaddingCalled = false
|
||||||
return {
|
return {
|
||||||
widerPadding: false,
|
widerPadding: false,
|
||||||
updateWiderPaddingCalled: false,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
beforeMount () {
|
||||||
this.updateWiderPadding = throttleByAnimationFrame(this.updateWiderPadding)
|
this.updateWiderPadding = throttleByAnimationFrame(this.updateWiderPadding)
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
this.updateWiderPadding()
|
this.updateWiderPadding()
|
||||||
this.resizeEvent = addEventListener(window, 'resize', this.updateWiderPadding)
|
this.resizeEvent = addEventListener(window, 'resize', this.updateWiderPadding)
|
||||||
|
|
||||||
// if (hasProp(this, 'noHovering')) {
|
|
||||||
// warning(
|
|
||||||
// !this.noHovering,
|
|
||||||
// '`noHovering` of Card is deperated, you can remove it safely or use `hoverable` instead.',
|
|
||||||
// )
|
|
||||||
// warning(!!this.noHovering, '`noHovering={false}` of Card is deperated, use `hoverable` instead.')
|
|
||||||
// }
|
|
||||||
},
|
},
|
||||||
beforeMount () {
|
beforeDestroy () {
|
||||||
if (this.resizeEvent) {
|
if (this.resizeEvent) {
|
||||||
this.resizeEvent.remove()
|
this.resizeEvent.remove()
|
||||||
}
|
}
|
||||||
|
@ -84,19 +76,11 @@
|
||||||
})
|
})
|
||||||
return containGrid
|
return containGrid
|
||||||
},
|
},
|
||||||
// For 2.x compatible
|
|
||||||
getCompatibleHoverable () {
|
|
||||||
const { noHovering, hoverable } = this.$props
|
|
||||||
if (hasProp(this, 'noHovering')) {
|
|
||||||
return !noHovering || hoverable
|
|
||||||
}
|
|
||||||
return !!hoverable
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
render () {
|
render () {
|
||||||
const {
|
const {
|
||||||
prefixCls = 'ant-card', extra, bodyStyle, title, loading,
|
prefixCls = 'ant-card', extra, bodyStyle, title, loading,
|
||||||
bordered = true, type, tabList, ...others
|
bordered = true, type, tabList, hoverable,
|
||||||
} = this.$props
|
} = this.$props
|
||||||
|
|
||||||
const { $slots } = this
|
const { $slots } = this
|
||||||
|
@ -105,7 +89,7 @@
|
||||||
[`${prefixCls}`]: true,
|
[`${prefixCls}`]: true,
|
||||||
[`${prefixCls}-loading`]: loading,
|
[`${prefixCls}-loading`]: loading,
|
||||||
[`${prefixCls}-bordered`]: bordered,
|
[`${prefixCls}-bordered`]: bordered,
|
||||||
[`${prefixCls}-hoverable`]: this.getCompatibleHoverable(),
|
[`${prefixCls}-hoverable`]: !!hoverable,
|
||||||
[`${prefixCls}-wider-padding`]: this.widerPadding,
|
[`${prefixCls}-wider-padding`]: this.widerPadding,
|
||||||
[`${prefixCls}-padding-transition`]: this.updateWiderPaddingCalled,
|
[`${prefixCls}-padding-transition`]: this.updateWiderPaddingCalled,
|
||||||
[`${prefixCls}-contain-grid`]: this.isContainGrid($slots.default),
|
[`${prefixCls}-contain-grid`]: this.isContainGrid($slots.default),
|
||||||
|
@ -166,11 +150,9 @@
|
||||||
)
|
)
|
||||||
const actions = getComponentFromProp(this, 'actions')
|
const actions = getComponentFromProp(this, 'actions')
|
||||||
const actionDom = actions || null
|
const actionDom = actions || null
|
||||||
const divProps = omit(others, [
|
|
||||||
'tabChange',
|
|
||||||
])
|
|
||||||
return (
|
return (
|
||||||
<div {...divProps} class={classString} ref='cardContainerRef'>
|
<div class={classString} ref='cardContainerRef'>
|
||||||
{head}
|
{head}
|
||||||
{coverDom}
|
{coverDom}
|
||||||
{children ? body : null}
|
{children ? body : null}
|
||||||
|
|
|
@ -89,3 +89,5 @@ export { default as LocaleProvider } from './locale-provider'
|
||||||
|
|
||||||
export { default as AutoComplete } from './auto-complete'
|
export { default as AutoComplete } from './auto-complete'
|
||||||
|
|
||||||
|
export { default as Affix } from './affix'
|
||||||
|
|
||||||
|
|
|
@ -24,3 +24,4 @@ import './spin/style'
|
||||||
import './select/style'
|
import './select/style'
|
||||||
import './switch/style'
|
import './switch/style'
|
||||||
import './auto-complete/style'
|
import './auto-complete/style'
|
||||||
|
import './affix/style'
|
||||||
|
|
|
@ -0,0 +1,313 @@
|
||||||
|
<script>
|
||||||
|
import React, { Component, cloneElement } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import Trigger from 'rc-trigger';
|
||||||
|
import Menus from './Menus';
|
||||||
|
import KeyCode from 'rc-util/lib/KeyCode';
|
||||||
|
import arrayTreeFilter from 'array-tree-filter';
|
||||||
|
import shallowEqualArrays from 'shallow-equal/arrays';
|
||||||
|
|
||||||
|
const BUILT_IN_PLACEMENTS = {
|
||||||
|
bottomLeft: {
|
||||||
|
points: ['tl', 'bl'],
|
||||||
|
offset: [0, 4],
|
||||||
|
overflow: {
|
||||||
|
adjustX: 1,
|
||||||
|
adjustY: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
topLeft: {
|
||||||
|
points: ['bl', 'tl'],
|
||||||
|
offset: [0, -4],
|
||||||
|
overflow: {
|
||||||
|
adjustX: 1,
|
||||||
|
adjustY: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
bottomRight: {
|
||||||
|
points: ['tr', 'br'],
|
||||||
|
offset: [0, 4],
|
||||||
|
overflow: {
|
||||||
|
adjustX: 1,
|
||||||
|
adjustY: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
topRight: {
|
||||||
|
points: ['br', 'tr'],
|
||||||
|
offset: [0, -4],
|
||||||
|
overflow: {
|
||||||
|
adjustX: 1,
|
||||||
|
adjustY: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
class Cascader extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
let initialValue = [];
|
||||||
|
if ('value' in props) {
|
||||||
|
initialValue = props.value || [];
|
||||||
|
} else if ('defaultValue' in props) {
|
||||||
|
initialValue = props.defaultValue || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
popupVisible: props.popupVisible,
|
||||||
|
activeValue: initialValue,
|
||||||
|
value: initialValue,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
if ('value' in nextProps && !shallowEqualArrays(this.props.value, nextProps.value)) {
|
||||||
|
const newValues = {
|
||||||
|
value: nextProps.value || [],
|
||||||
|
activeValue: nextProps.value || [],
|
||||||
|
};
|
||||||
|
// allow activeValue diff from value
|
||||||
|
// https://github.com/ant-design/ant-design/issues/2767
|
||||||
|
if ('loadData' in nextProps) {
|
||||||
|
delete newValues.activeValue;
|
||||||
|
}
|
||||||
|
this.setState(newValues);
|
||||||
|
}
|
||||||
|
if ('popupVisible' in nextProps) {
|
||||||
|
this.setState({
|
||||||
|
popupVisible: nextProps.popupVisible,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getPopupDOMNode() {
|
||||||
|
return this.trigger.getPopupDomNode();
|
||||||
|
}
|
||||||
|
getCurrentLevelOptions() {
|
||||||
|
const { options } = this.props;
|
||||||
|
const { activeValue = [] } = this.state;
|
||||||
|
const result = arrayTreeFilter(options, (o, level) => o.value === activeValue[level]);
|
||||||
|
if (result[result.length - 2]) {
|
||||||
|
return result[result.length - 2].children;
|
||||||
|
}
|
||||||
|
return [...options].filter(o => !o.disabled);
|
||||||
|
}
|
||||||
|
getActiveOptions(activeValue) {
|
||||||
|
return arrayTreeFilter(this.props.options, (o, level) => o.value === activeValue[level]);
|
||||||
|
}
|
||||||
|
setPopupVisible = (popupVisible) => {
|
||||||
|
if (!('popupVisible' in this.props)) {
|
||||||
|
this.setState({ popupVisible });
|
||||||
|
}
|
||||||
|
// sync activeValue with value when panel open
|
||||||
|
if (popupVisible && !this.state.visible) {
|
||||||
|
this.setState({
|
||||||
|
activeValue: this.state.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.props.onPopupVisibleChange(popupVisible);
|
||||||
|
}
|
||||||
|
handleChange = (options, setProps, e) => {
|
||||||
|
if (e.type !== 'keydown' || e.keyCode === KeyCode.ENTER) {
|
||||||
|
this.props.onChange(options.map(o => o.value), options);
|
||||||
|
this.setPopupVisible(setProps.visible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handlePopupVisibleChange = (popupVisible) => {
|
||||||
|
this.setPopupVisible(popupVisible);
|
||||||
|
}
|
||||||
|
handleMenuSelect = (targetOption, menuIndex, e) => {
|
||||||
|
// Keep focused state for keyboard support
|
||||||
|
const triggerNode = this.trigger.getRootDomNode();
|
||||||
|
if (triggerNode && triggerNode.focus) {
|
||||||
|
triggerNode.focus();
|
||||||
|
}
|
||||||
|
const { changeOnSelect, loadData, expandTrigger } = this.props;
|
||||||
|
if (!targetOption || targetOption.disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let { activeValue } = this.state;
|
||||||
|
activeValue = activeValue.slice(0, menuIndex + 1);
|
||||||
|
activeValue[menuIndex] = targetOption.value;
|
||||||
|
const activeOptions = this.getActiveOptions(activeValue);
|
||||||
|
if (targetOption.isLeaf === false && !targetOption.children && loadData) {
|
||||||
|
if (changeOnSelect) {
|
||||||
|
this.handleChange(activeOptions, { visible: true }, e);
|
||||||
|
}
|
||||||
|
this.setState({ activeValue });
|
||||||
|
loadData(activeOptions);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const newState = {};
|
||||||
|
if (!targetOption.children || !targetOption.children.length) {
|
||||||
|
this.handleChange(activeOptions, { visible: false }, e);
|
||||||
|
// set value to activeValue when select leaf option
|
||||||
|
newState.value = activeValue;
|
||||||
|
// add e.type judgement to prevent `onChange` being triggered by mouseEnter
|
||||||
|
} else if (changeOnSelect && (e.type === 'click' || e.type === 'keydown')) {
|
||||||
|
if (expandTrigger === 'hover') {
|
||||||
|
this.handleChange(activeOptions, { visible: false }, e);
|
||||||
|
} else {
|
||||||
|
this.handleChange(activeOptions, { visible: true }, e);
|
||||||
|
}
|
||||||
|
// set value to activeValue on every select
|
||||||
|
newState.value = activeValue;
|
||||||
|
}
|
||||||
|
newState.activeValue = activeValue;
|
||||||
|
// not change the value by keyboard
|
||||||
|
if ('value' in this.props ||
|
||||||
|
(e.type === 'keydown' && e.keyCode !== KeyCode.ENTER)) {
|
||||||
|
delete newState.value;
|
||||||
|
}
|
||||||
|
this.setState(newState);
|
||||||
|
}
|
||||||
|
handleKeyDown = (e) => {
|
||||||
|
const { children } = this.props;
|
||||||
|
// https://github.com/ant-design/ant-design/issues/6717
|
||||||
|
// Don't bind keyboard support when children specify the onKeyDown
|
||||||
|
if (children && children.props.onKeyDown) {
|
||||||
|
children.props.onKeyDown(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const activeValue = [...this.state.activeValue];
|
||||||
|
const currentLevel = activeValue.length - 1 < 0 ? 0 : activeValue.length - 1;
|
||||||
|
const currentOptions = this.getCurrentLevelOptions();
|
||||||
|
const currentIndex = currentOptions.map(o => o.value).indexOf(activeValue[currentLevel]);
|
||||||
|
if (e.keyCode !== KeyCode.DOWN &&
|
||||||
|
e.keyCode !== KeyCode.UP &&
|
||||||
|
e.keyCode !== KeyCode.LEFT &&
|
||||||
|
e.keyCode !== KeyCode.RIGHT &&
|
||||||
|
e.keyCode !== KeyCode.ENTER &&
|
||||||
|
e.keyCode !== KeyCode.BACKSPACE &&
|
||||||
|
e.keyCode !== KeyCode.ESC) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Press any keys above to reopen menu
|
||||||
|
if (!this.state.popupVisible &&
|
||||||
|
e.keyCode !== KeyCode.BACKSPACE &&
|
||||||
|
e.keyCode !== KeyCode.LEFT &&
|
||||||
|
e.keyCode !== KeyCode.RIGHT &&
|
||||||
|
e.keyCode !== KeyCode.ESC) {
|
||||||
|
this.setPopupVisible(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.keyCode === KeyCode.DOWN || e.keyCode === KeyCode.UP) {
|
||||||
|
let nextIndex = currentIndex;
|
||||||
|
if (nextIndex !== -1) {
|
||||||
|
if (e.keyCode === KeyCode.DOWN) {
|
||||||
|
nextIndex += 1;
|
||||||
|
nextIndex = nextIndex >= currentOptions.length ? 0 : nextIndex;
|
||||||
|
} else {
|
||||||
|
nextIndex -= 1;
|
||||||
|
nextIndex = nextIndex < 0 ? currentOptions.length - 1 : nextIndex;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nextIndex = 0;
|
||||||
|
}
|
||||||
|
activeValue[currentLevel] = currentOptions[nextIndex].value;
|
||||||
|
} else if (e.keyCode === KeyCode.LEFT || e.keyCode === KeyCode.BACKSPACE) {
|
||||||
|
activeValue.splice(activeValue.length - 1, 1);
|
||||||
|
} else if (e.keyCode === KeyCode.RIGHT) {
|
||||||
|
if (currentOptions[currentIndex] && currentOptions[currentIndex].children) {
|
||||||
|
activeValue.push(currentOptions[currentIndex].children[0].value);
|
||||||
|
}
|
||||||
|
} else if (e.keyCode === KeyCode.ESC) {
|
||||||
|
this.setPopupVisible(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!activeValue || activeValue.length === 0) {
|
||||||
|
this.setPopupVisible(false);
|
||||||
|
}
|
||||||
|
const activeOptions = this.getActiveOptions(activeValue);
|
||||||
|
const targetOption = activeOptions[activeOptions.length - 1];
|
||||||
|
this.handleMenuSelect(targetOption, activeOptions.length - 1, e);
|
||||||
|
|
||||||
|
if (this.props.onKeyDown) {
|
||||||
|
this.props.onKeyDown(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
saveTrigger = (node) => {
|
||||||
|
this.trigger = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
prefixCls, transitionName, popupClassName, options, disabled,
|
||||||
|
builtinPlacements, popupPlacement, children, ...restProps,
|
||||||
|
} = this.props;
|
||||||
|
// Did not show popup when there is no options
|
||||||
|
let menus = <div />;
|
||||||
|
let emptyMenuClassName = '';
|
||||||
|
if (options && options.length > 0) {
|
||||||
|
menus = (
|
||||||
|
<Menus
|
||||||
|
{...this.props}
|
||||||
|
value={this.state.value}
|
||||||
|
activeValue={this.state.activeValue}
|
||||||
|
onSelect={this.handleMenuSelect}
|
||||||
|
visible={this.state.popupVisible}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
emptyMenuClassName = ` ${prefixCls}-menus-empty`;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Trigger
|
||||||
|
ref={this.saveTrigger}
|
||||||
|
{...restProps}
|
||||||
|
options={options}
|
||||||
|
disabled={disabled}
|
||||||
|
popupPlacement={popupPlacement}
|
||||||
|
builtinPlacements={builtinPlacements}
|
||||||
|
popupTransitionName={transitionName}
|
||||||
|
action={disabled ? [] : ['click']}
|
||||||
|
popupVisible={disabled ? false : this.state.popupVisible}
|
||||||
|
onPopupVisibleChange={this.handlePopupVisibleChange}
|
||||||
|
prefixCls={`${prefixCls}-menus`}
|
||||||
|
popupClassName={popupClassName + emptyMenuClassName}
|
||||||
|
popup={menus}
|
||||||
|
>
|
||||||
|
{cloneElement(children, {
|
||||||
|
onKeyDown: this.handleKeyDown,
|
||||||
|
tabIndex: disabled ? undefined : 0,
|
||||||
|
})}
|
||||||
|
</Trigger>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Cascader.defaultProps = {
|
||||||
|
options: [],
|
||||||
|
onChange() {},
|
||||||
|
onPopupVisibleChange() {},
|
||||||
|
disabled: false,
|
||||||
|
transitionName: '',
|
||||||
|
prefixCls: 'rc-cascader',
|
||||||
|
popupClassName: '',
|
||||||
|
popupPlacement: 'bottomLeft',
|
||||||
|
builtinPlacements: BUILT_IN_PLACEMENTS,
|
||||||
|
expandTrigger: 'click',
|
||||||
|
};
|
||||||
|
|
||||||
|
Cascader.propTypes = {
|
||||||
|
value: PropTypes.array,
|
||||||
|
defaultValue: PropTypes.array,
|
||||||
|
options: PropTypes.array.isRequired,
|
||||||
|
onChange: PropTypes.func,
|
||||||
|
onPopupVisibleChange: PropTypes.func,
|
||||||
|
popupVisible: PropTypes.bool,
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
transitionName: PropTypes.string,
|
||||||
|
popupClassName: PropTypes.string,
|
||||||
|
popupPlacement: PropTypes.string,
|
||||||
|
prefixCls: PropTypes.string,
|
||||||
|
dropdownMenuColumnStyle: PropTypes.object,
|
||||||
|
builtinPlacements: PropTypes.object,
|
||||||
|
loadData: PropTypes.func,
|
||||||
|
changeOnSelect: PropTypes.bool,
|
||||||
|
children: PropTypes.node,
|
||||||
|
onKeyDown: PropTypes.func,
|
||||||
|
expandTrigger: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Cascader;
|
||||||
|
|
||||||
|
</script>
|
|
@ -0,0 +1,156 @@
|
||||||
|
<script>
|
||||||
|
import React from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import arrayTreeFilter from 'array-tree-filter'
|
||||||
|
import { findDOMNode } from 'react-dom'
|
||||||
|
|
||||||
|
class Menus extends React.Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this.menuItems = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount () {
|
||||||
|
this.scrollActiveItemToView()
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate (prevProps) {
|
||||||
|
if (!prevProps.visible && this.props.visible) {
|
||||||
|
this.scrollActiveItemToView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getOption (option, menuIndex) {
|
||||||
|
const { prefixCls, expandTrigger } = this.props
|
||||||
|
const onSelect = this.props.onSelect.bind(this, option, menuIndex)
|
||||||
|
let expandProps = {
|
||||||
|
onClick: onSelect,
|
||||||
|
}
|
||||||
|
let menuItemCls = `${prefixCls}-menu-item`
|
||||||
|
const hasChildren = option.children && option.children.length > 0
|
||||||
|
if (hasChildren || option.isLeaf === false) {
|
||||||
|
menuItemCls += ` ${prefixCls}-menu-item-expand`
|
||||||
|
}
|
||||||
|
if (expandTrigger === 'hover' && hasChildren) {
|
||||||
|
expandProps = {
|
||||||
|
onMouseEnter: this.delayOnSelect.bind(this, onSelect),
|
||||||
|
onMouseLeave: this.delayOnSelect.bind(this),
|
||||||
|
onClick: onSelect,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.isActiveOption(option, menuIndex)) {
|
||||||
|
menuItemCls += ` ${prefixCls}-menu-item-active`
|
||||||
|
expandProps.ref = this.saveMenuItem(menuIndex)
|
||||||
|
}
|
||||||
|
if (option.disabled) {
|
||||||
|
menuItemCls += ` ${prefixCls}-menu-item-disabled`
|
||||||
|
}
|
||||||
|
if (option.loading) {
|
||||||
|
menuItemCls += ` ${prefixCls}-menu-item-loading`
|
||||||
|
}
|
||||||
|
let title = ''
|
||||||
|
if (option.title) {
|
||||||
|
title = option.title
|
||||||
|
} else if (typeof option.label === 'string') {
|
||||||
|
title = option.label
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<li
|
||||||
|
key={option.value}
|
||||||
|
className={menuItemCls}
|
||||||
|
title={title}
|
||||||
|
{...expandProps}
|
||||||
|
>
|
||||||
|
{option.label}
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
getActiveOptions (values) {
|
||||||
|
const activeValue = values || this.props.activeValue
|
||||||
|
const options = this.props.options
|
||||||
|
return arrayTreeFilter(options, (o, level) => o.value === activeValue[level])
|
||||||
|
}
|
||||||
|
|
||||||
|
getShowOptions () {
|
||||||
|
const { options } = this.props
|
||||||
|
const result = this.getActiveOptions()
|
||||||
|
.map(activeOption => activeOption.children)
|
||||||
|
.filter(activeOption => !!activeOption)
|
||||||
|
result.unshift(options)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
delayOnSelect (onSelect, ...args) {
|
||||||
|
if (this.delayTimer) {
|
||||||
|
clearTimeout(this.delayTimer)
|
||||||
|
this.delayTimer = null
|
||||||
|
}
|
||||||
|
if (typeof onSelect === 'function') {
|
||||||
|
this.delayTimer = setTimeout(() => {
|
||||||
|
onSelect(args)
|
||||||
|
this.delayTimer = null
|
||||||
|
}, 150)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollActiveItemToView () {
|
||||||
|
// scroll into view
|
||||||
|
const optionsLength = this.getShowOptions().length
|
||||||
|
for (let i = 0; i < optionsLength; i++) {
|
||||||
|
const itemComponent = this.menuItems[i]
|
||||||
|
if (itemComponent) {
|
||||||
|
const target = findDOMNode(itemComponent)
|
||||||
|
target.parentNode.scrollTop = target.offsetTop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isActiveOption (option, menuIndex) {
|
||||||
|
const { activeValue = [] } = this.props
|
||||||
|
return activeValue[menuIndex] === option.value
|
||||||
|
}
|
||||||
|
|
||||||
|
saveMenuItem = (index) => (node) => {
|
||||||
|
this.menuItems[index] = node
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { prefixCls, dropdownMenuColumnStyle } = this.props
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{this.getShowOptions().map((options, menuIndex) =>
|
||||||
|
<ul className={`${prefixCls}-menu`} key={menuIndex} style={dropdownMenuColumnStyle}>
|
||||||
|
{options.map(option => this.getOption(option, menuIndex))}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Menus.defaultProps = {
|
||||||
|
options: [],
|
||||||
|
value: [],
|
||||||
|
activeValue: [],
|
||||||
|
onSelect () {},
|
||||||
|
prefixCls: 'rc-cascader-menus',
|
||||||
|
visible: false,
|
||||||
|
expandTrigger: 'click',
|
||||||
|
}
|
||||||
|
|
||||||
|
Menus.propTypes = {
|
||||||
|
value: PropTypes.array,
|
||||||
|
activeValue: PropTypes.array,
|
||||||
|
options: PropTypes.array.isRequired,
|
||||||
|
prefixCls: PropTypes.string,
|
||||||
|
expandTrigger: PropTypes.string,
|
||||||
|
onSelect: PropTypes.func,
|
||||||
|
visible: PropTypes.bool,
|
||||||
|
dropdownMenuColumnStyle: PropTypes.object,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Menus
|
||||||
|
|
||||||
|
</script>
|
|
@ -0,0 +1,167 @@
|
||||||
|
.effect() {
|
||||||
|
animation-duration: .3s;
|
||||||
|
animation-fill-mode: both;
|
||||||
|
transform-origin: 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rc-cascader {
|
||||||
|
font-size: 12px;
|
||||||
|
&-menus {
|
||||||
|
font-size: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #fff;
|
||||||
|
position: absolute;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 0 0 4px rgba(0,0,0,0.17);
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&-hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.slide-up-enter, &.slide-up-appear {
|
||||||
|
.effect();
|
||||||
|
opacity: 0;
|
||||||
|
animation-timing-function: cubic-bezier(0.08, 0.82, 0.17, 1);
|
||||||
|
animation-play-state: paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.slide-up-leave {
|
||||||
|
.effect();
|
||||||
|
opacity: 1;
|
||||||
|
animation-timing-function: cubic-bezier(0.6, 0.04, 0.98, 0.34);
|
||||||
|
animation-play-state: paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.slide-up-enter.slide-up-enter-active&-placement-bottomLeft,
|
||||||
|
&.slide-up-appear.slide-up-appear-active&-placement-bottomLeft {
|
||||||
|
animation-name: SlideUpIn;
|
||||||
|
animation-play-state: running;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.slide-up-enter.slide-up-enter-active&-placement-topLeft,
|
||||||
|
&.slide-up-appear.slide-up-appear-active&-placement-topLeft {
|
||||||
|
animation-name: SlideDownIn;
|
||||||
|
animation-play-state: running;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.slide-up-leave.slide-up-leave-active&-placement-bottomLeft {
|
||||||
|
animation-name: SlideUpOut;
|
||||||
|
animation-play-state: running;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.slide-up-leave.slide-up-leave-active&-placement-topLeft {
|
||||||
|
animation-name: SlideDownOut;
|
||||||
|
animation-play-state: running;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&-menu {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100px;
|
||||||
|
height: 192px;
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border-right: 1px solid #e9e9e9;
|
||||||
|
overflow: auto;
|
||||||
|
&:last-child {
|
||||||
|
border-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&-menu-item {
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
padding: 0 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
position: relative;
|
||||||
|
&:hover {
|
||||||
|
background: tint(#2db7f5, 90%);
|
||||||
|
}
|
||||||
|
&-disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
color: #ccc;
|
||||||
|
&:hover {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&-loading:after {
|
||||||
|
position: absolute;
|
||||||
|
right: 12px;
|
||||||
|
content: 'loading';
|
||||||
|
color: #aaa;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
&-active {
|
||||||
|
background: tint(#2db7f5, 80%);
|
||||||
|
&:hover {
|
||||||
|
background: tint(#2db7f5, 80%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&-expand {
|
||||||
|
position: relative;
|
||||||
|
&:after {
|
||||||
|
content: '>';
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
position: absolute;
|
||||||
|
right: 16px;
|
||||||
|
line-height: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes SlideUpIn {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform-origin: 0% 0%;
|
||||||
|
transform: scaleY(.8);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
transform-origin: 0% 0%;
|
||||||
|
transform: scaleY(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes SlideUpOut {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
transform-origin: 0% 0%;
|
||||||
|
transform: scaleY(1);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
transform-origin: 0% 0%;
|
||||||
|
transform: scaleY(0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes SlideDownIn {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform-origin: 0% 100%;
|
||||||
|
transform: scaleY(0.8);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
transform-origin: 0% 100%;
|
||||||
|
transform: scaleY(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes SlideDownOut {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
transform-origin: 0% 100%;
|
||||||
|
transform: scaleY(1);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
transform-origin: 0% 100%;
|
||||||
|
transform: scaleY(0.8);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
// export this package's api
|
||||||
|
import Cascader from './Cascader'
|
||||||
|
export default Cascader
|
|
@ -15,9 +15,6 @@ export default {
|
||||||
props: {
|
props: {
|
||||||
...switchPropTypes,
|
...switchPropTypes,
|
||||||
prefixCls: switchPropTypes.prefixCls.def('rc-switch'),
|
prefixCls: switchPropTypes.prefixCls.def('rc-switch'),
|
||||||
checkedChildren: switchPropTypes.checkedChildren,
|
|
||||||
unCheckedChildren: switchPropTypes.unCheckedChildren,
|
|
||||||
defaultChecked: switchPropTypes.defaultChecked.def(''),
|
|
||||||
// onChange: switchPropTypes.onChange.def(noop),
|
// onChange: switchPropTypes.onChange.def(noop),
|
||||||
// onClick: switchPropTypes.onClick.def(noop),
|
// onClick: switchPropTypes.onClick.def(noop),
|
||||||
},
|
},
|
||||||
|
|
|
@ -19,6 +19,8 @@ Select | done
|
||||||
Input | done
|
Input | done
|
||||||
InputNumber
|
InputNumber
|
||||||
AutoComplete | done
|
AutoComplete | done
|
||||||
|
Affix | done
|
||||||
|
Cascader
|
||||||
Modal
|
Modal
|
||||||
Alert
|
Alert
|
||||||
Calendar
|
Calendar
|
||||||
|
@ -32,7 +34,6 @@ Mention
|
||||||
##万
|
##万
|
||||||
Grid
|
Grid
|
||||||
Col
|
Col
|
||||||
Affix
|
|
||||||
BackTop
|
BackTop
|
||||||
Layout
|
Layout
|
||||||
Anchor
|
Anchor
|
||||||
|
|
|
@ -25,4 +25,5 @@ export { default as message } from 'antd/message/demo/index.vue'
|
||||||
export { default as spin } from 'antd/spin/demo/index.vue'
|
export { default as spin } from 'antd/spin/demo/index.vue'
|
||||||
export { default as switch } from 'antd/switch/demo/index.vue'
|
export { default as switch } from 'antd/switch/demo/index.vue'
|
||||||
export { default as autoComplete } from 'antd/auto-complete/demo/index.vue'
|
export { default as autoComplete } from 'antd/auto-complete/demo/index.vue'
|
||||||
|
export { default as affix } from 'antd/Affix/demo/index.vue'
|
||||||
|
|
||||||
|
|
|
@ -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/auto-complete/demo/${d}`),
|
component: import(`../components/affix/demo/${d}`),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export default [
|
export default [
|
||||||
|
|
|
@ -100,6 +100,7 @@
|
||||||
"lodash.isplainobject": "^4.0.6",
|
"lodash.isplainobject": "^4.0.6",
|
||||||
"moment": "^2.20.1",
|
"moment": "^2.20.1",
|
||||||
"omit.js": "^1.0.0",
|
"omit.js": "^1.0.0",
|
||||||
|
"shallowequal": "^1.0.2",
|
||||||
"vue": "^2.5.13",
|
"vue": "^2.5.13",
|
||||||
"vue-clipboard2": "0.0.8",
|
"vue-clipboard2": "0.0.8",
|
||||||
"vue-types": "^1.0.2",
|
"vue-types": "^1.0.2",
|
||||||
|
|
Loading…
Reference in New Issue