fix
parent
8736a23884
commit
37b40bcd38
|
@ -3,6 +3,7 @@ import PropTypes from 'vue-types'
|
|||
import align from 'dom-align'
|
||||
import addEventListener from '../_util/Dom/addEventListener'
|
||||
import cloneElement from '../_util/cloneElement'
|
||||
import isWindow from './isWindow'
|
||||
function noop () {
|
||||
}
|
||||
|
||||
|
@ -35,7 +36,39 @@ export default {
|
|||
monitorWindowResize: PropTypes.bool.def(false),
|
||||
disabled: PropTypes.bool.def(false),
|
||||
},
|
||||
watch: {
|
||||
'$props': {
|
||||
handler: function (props, prevProps) {
|
||||
this.$nextTick(() => {
|
||||
let reAlign = false
|
||||
if (!props.disabled) {
|
||||
if (prevProps.disabled || prevProps.align !== props.align) {
|
||||
reAlign = true
|
||||
} else {
|
||||
const lastTarget = prevProps.target()
|
||||
const currentTarget = props.target()
|
||||
if (isWindow(lastTarget) && isWindow(currentTarget)) {
|
||||
reAlign = false
|
||||
} else if (lastTarget !== currentTarget) {
|
||||
reAlign = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (reAlign) {
|
||||
this.forceAlign()
|
||||
}
|
||||
|
||||
if (props.monitorWindowResize && !props.disabled) {
|
||||
this.startMonitorWindowResize()
|
||||
} else {
|
||||
this.stopMonitorWindowResize()
|
||||
}
|
||||
})
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
mounted () {
|
||||
const props = this.$props
|
||||
// if parent ref not attached .... use document.getElementById
|
||||
|
@ -44,20 +77,7 @@ export default {
|
|||
this.startMonitorWindowResize()
|
||||
}
|
||||
},
|
||||
|
||||
updated () {
|
||||
const props = this.$props
|
||||
|
||||
this.forceAlign()
|
||||
|
||||
if (props.monitorWindowResize && !props.disabled) {
|
||||
this.startMonitorWindowResize()
|
||||
} else {
|
||||
this.stopMonitorWindowResize()
|
||||
}
|
||||
},
|
||||
|
||||
beforeDestory () {
|
||||
beforeDestroy () {
|
||||
this.stopMonitorWindowResize()
|
||||
},
|
||||
methods: {
|
||||
|
@ -86,6 +106,7 @@ export default {
|
|||
},
|
||||
|
||||
render () {
|
||||
console.log(4)
|
||||
const { childrenProps } = this.$props
|
||||
const child = this.$slots.default[0]
|
||||
if (childrenProps) {
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
// do not modify this file
|
||||
import Animate from './src/Animate'
|
||||
export default Animate
|
|
@ -1,333 +0,0 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {
|
||||
toArrayChildren,
|
||||
mergeChildren,
|
||||
findShownChildInChildrenByKey,
|
||||
findChildInChildrenByKey,
|
||||
isSameChildren,
|
||||
} from './ChildrenUtils'
|
||||
import AnimateChild from './AnimateChild'
|
||||
const defaultKey = `rc_animate_${Date.now()}`
|
||||
import animUtil from './util'
|
||||
|
||||
function getChildrenFromProps (props) {
|
||||
const children = props.children
|
||||
if (React.isValidElement(children)) {
|
||||
if (!children.key) {
|
||||
return React.cloneElement(children, {
|
||||
key: defaultKey,
|
||||
})
|
||||
}
|
||||
}
|
||||
return children
|
||||
}
|
||||
|
||||
function noop () {
|
||||
}
|
||||
|
||||
export default class Animate extends React.Component {
|
||||
static propTypes = {
|
||||
component: PropTypes.any,
|
||||
componentProps: PropTypes.object,
|
||||
animation: PropTypes.object,
|
||||
transitionName: PropTypes.oneOfType([
|
||||
PropTypes.string,
|
||||
PropTypes.object,
|
||||
]),
|
||||
transitionEnter: PropTypes.bool,
|
||||
transitionAppear: PropTypes.bool,
|
||||
exclusive: PropTypes.bool,
|
||||
transitionLeave: PropTypes.bool,
|
||||
onEnd: PropTypes.func,
|
||||
onEnter: PropTypes.func,
|
||||
onLeave: PropTypes.func,
|
||||
onAppear: PropTypes.func,
|
||||
showProp: PropTypes.string,
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
animation: {},
|
||||
component: 'span',
|
||||
componentProps: {},
|
||||
transitionEnter: true,
|
||||
transitionLeave: true,
|
||||
transitionAppear: false,
|
||||
onEnd: noop,
|
||||
onEnter: noop,
|
||||
onLeave: noop,
|
||||
onAppear: noop,
|
||||
}
|
||||
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.currentlyAnimatingKeys = {}
|
||||
this.keysToEnter = []
|
||||
this.keysToLeave = []
|
||||
|
||||
this.state = {
|
||||
children: toArrayChildren(getChildrenFromProps(this.props)),
|
||||
}
|
||||
|
||||
this.childrenRefs = {}
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
const showProp = this.props.showProp
|
||||
let children = this.state.children
|
||||
if (showProp) {
|
||||
children = children.filter((child) => {
|
||||
return !!child.props[showProp]
|
||||
})
|
||||
}
|
||||
children.forEach((child) => {
|
||||
if (child) {
|
||||
this.performAppear(child.key)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
this.nextProps = nextProps
|
||||
const nextChildren = toArrayChildren(getChildrenFromProps(nextProps))
|
||||
const props = this.props
|
||||
// exclusive needs immediate response
|
||||
if (props.exclusive) {
|
||||
Object.keys(this.currentlyAnimatingKeys).forEach((key) => {
|
||||
this.stop(key)
|
||||
})
|
||||
}
|
||||
const showProp = props.showProp
|
||||
const currentlyAnimatingKeys = this.currentlyAnimatingKeys
|
||||
// last props children if exclusive
|
||||
const currentChildren = props.exclusive
|
||||
? toArrayChildren(getChildrenFromProps(props))
|
||||
: this.state.children
|
||||
// in case destroy in showProp mode
|
||||
let newChildren = []
|
||||
if (showProp) {
|
||||
currentChildren.forEach((currentChild) => {
|
||||
const nextChild = currentChild && findChildInChildrenByKey(nextChildren, currentChild.key)
|
||||
let newChild
|
||||
if ((!nextChild || !nextChild.props[showProp]) && currentChild.props[showProp]) {
|
||||
newChild = React.cloneElement(nextChild || currentChild, {
|
||||
[showProp]: true,
|
||||
})
|
||||
} else {
|
||||
newChild = nextChild
|
||||
}
|
||||
if (newChild) {
|
||||
newChildren.push(newChild)
|
||||
}
|
||||
})
|
||||
nextChildren.forEach((nextChild) => {
|
||||
if (!nextChild || !findChildInChildrenByKey(currentChildren, nextChild.key)) {
|
||||
newChildren.push(nextChild)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
newChildren = mergeChildren(
|
||||
currentChildren,
|
||||
nextChildren
|
||||
)
|
||||
}
|
||||
|
||||
// need render to avoid update
|
||||
this.setState({
|
||||
children: newChildren,
|
||||
})
|
||||
|
||||
nextChildren.forEach((child) => {
|
||||
const key = child && child.key
|
||||
if (child && currentlyAnimatingKeys[key]) {
|
||||
return
|
||||
}
|
||||
const hasPrev = child && findChildInChildrenByKey(currentChildren, key)
|
||||
if (showProp) {
|
||||
const showInNext = child.props[showProp]
|
||||
if (hasPrev) {
|
||||
const showInNow = findShownChildInChildrenByKey(currentChildren, key, showProp)
|
||||
if (!showInNow && showInNext) {
|
||||
this.keysToEnter.push(key)
|
||||
}
|
||||
} else if (showInNext) {
|
||||
this.keysToEnter.push(key)
|
||||
}
|
||||
} else if (!hasPrev) {
|
||||
this.keysToEnter.push(key)
|
||||
}
|
||||
})
|
||||
|
||||
currentChildren.forEach((child) => {
|
||||
const key = child && child.key
|
||||
if (child && currentlyAnimatingKeys[key]) {
|
||||
return
|
||||
}
|
||||
const hasNext = child && findChildInChildrenByKey(nextChildren, key)
|
||||
if (showProp) {
|
||||
const showInNow = child.props[showProp]
|
||||
if (hasNext) {
|
||||
const showInNext = findShownChildInChildrenByKey(nextChildren, key, showProp)
|
||||
if (!showInNext && showInNow) {
|
||||
this.keysToLeave.push(key)
|
||||
}
|
||||
} else if (showInNow) {
|
||||
this.keysToLeave.push(key)
|
||||
}
|
||||
} else if (!hasNext) {
|
||||
this.keysToLeave.push(key)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
componentDidUpdate () {
|
||||
const keysToEnter = this.keysToEnter
|
||||
this.keysToEnter = []
|
||||
keysToEnter.forEach(this.performEnter)
|
||||
const keysToLeave = this.keysToLeave
|
||||
this.keysToLeave = []
|
||||
keysToLeave.forEach(this.performLeave)
|
||||
}
|
||||
|
||||
performEnter = (key) => {
|
||||
// may already remove by exclusive
|
||||
if (this.childrenRefs[key]) {
|
||||
this.currentlyAnimatingKeys[key] = true
|
||||
this.childrenRefs[key].componentWillEnter(
|
||||
this.handleDoneAdding.bind(this, key, 'enter')
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
performAppear = (key) => {
|
||||
if (this.childrenRefs[key]) {
|
||||
this.currentlyAnimatingKeys[key] = true
|
||||
this.childrenRefs[key].componentWillAppear(
|
||||
this.handleDoneAdding.bind(this, key, 'appear')
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
handleDoneAdding = (key, type) => {
|
||||
const props = this.props
|
||||
delete this.currentlyAnimatingKeys[key]
|
||||
// if update on exclusive mode, skip check
|
||||
if (props.exclusive && props !== this.nextProps) {
|
||||
return
|
||||
}
|
||||
const currentChildren = toArrayChildren(getChildrenFromProps(props))
|
||||
if (!this.isValidChildByKey(currentChildren, key)) {
|
||||
// exclusive will not need this
|
||||
this.performLeave(key)
|
||||
} else {
|
||||
if (type === 'appear') {
|
||||
if (animUtil.allowAppearCallback(props)) {
|
||||
props.onAppear(key)
|
||||
props.onEnd(key, true)
|
||||
}
|
||||
} else {
|
||||
if (animUtil.allowEnterCallback(props)) {
|
||||
props.onEnter(key)
|
||||
props.onEnd(key, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
performLeave = (key) => {
|
||||
// may already remove by exclusive
|
||||
if (this.childrenRefs[key]) {
|
||||
this.currentlyAnimatingKeys[key] = true
|
||||
this.childrenRefs[key].componentWillLeave(this.handleDoneLeaving.bind(this, key))
|
||||
}
|
||||
}
|
||||
|
||||
handleDoneLeaving = (key) => {
|
||||
const props = this.props
|
||||
delete this.currentlyAnimatingKeys[key]
|
||||
// if update on exclusive mode, skip check
|
||||
if (props.exclusive && props !== this.nextProps) {
|
||||
return
|
||||
}
|
||||
const currentChildren = toArrayChildren(getChildrenFromProps(props))
|
||||
// in case state change is too fast
|
||||
if (this.isValidChildByKey(currentChildren, key)) {
|
||||
this.performEnter(key)
|
||||
} else {
|
||||
const end = () => {
|
||||
if (animUtil.allowLeaveCallback(props)) {
|
||||
props.onLeave(key)
|
||||
props.onEnd(key, false)
|
||||
}
|
||||
}
|
||||
if (!isSameChildren(this.state.children,
|
||||
currentChildren, props.showProp)) {
|
||||
this.setState({
|
||||
children: currentChildren,
|
||||
}, end)
|
||||
} else {
|
||||
end()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isValidChildByKey (currentChildren, key) {
|
||||
const showProp = this.props.showProp
|
||||
if (showProp) {
|
||||
return findShownChildInChildrenByKey(currentChildren, key, showProp)
|
||||
}
|
||||
return findChildInChildrenByKey(currentChildren, key)
|
||||
}
|
||||
|
||||
stop (key) {
|
||||
delete this.currentlyAnimatingKeys[key]
|
||||
const component = this.childrenRefs[key]
|
||||
if (component) {
|
||||
component.stop()
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const props = this.props
|
||||
this.nextProps = props
|
||||
const stateChildren = this.state.children
|
||||
let children = null
|
||||
if (stateChildren) {
|
||||
children = stateChildren.map((child) => {
|
||||
if (child === null || child === undefined) {
|
||||
return child
|
||||
}
|
||||
if (!child.key) {
|
||||
throw new Error('must set key for <rc-animate> children')
|
||||
}
|
||||
return (
|
||||
<AnimateChild
|
||||
key={child.key}
|
||||
ref={node => this.childrenRefs[child.key] = node}
|
||||
animation={props.animation}
|
||||
transitionName={props.transitionName}
|
||||
transitionEnter={props.transitionEnter}
|
||||
transitionAppear={props.transitionAppear}
|
||||
transitionLeave={props.transitionLeave}
|
||||
>
|
||||
{child}
|
||||
</AnimateChild>
|
||||
)
|
||||
})
|
||||
}
|
||||
const Component = props.component
|
||||
if (Component) {
|
||||
let passedProps = props
|
||||
if (typeof Component === 'string') {
|
||||
passedProps = {
|
||||
className: props.className,
|
||||
style: props.style,
|
||||
...props.componentProps,
|
||||
}
|
||||
}
|
||||
return <Component {...passedProps}>{children}</Component>
|
||||
}
|
||||
return children[0] || null
|
||||
}
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import PropTypes from 'prop-types'
|
||||
import cssAnimate, { isCssAnimationSupported } from 'css-animation'
|
||||
import animUtil from './util'
|
||||
|
||||
const transitionMap = {
|
||||
enter: 'transitionEnter',
|
||||
appear: 'transitionAppear',
|
||||
leave: 'transitionLeave',
|
||||
}
|
||||
|
||||
export default class AnimateChild extends React.Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.any,
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
this.stop()
|
||||
}
|
||||
|
||||
componentWillEnter (done) {
|
||||
if (animUtil.isEnterSupported(this.props)) {
|
||||
this.transition('enter', done)
|
||||
} else {
|
||||
done()
|
||||
}
|
||||
}
|
||||
|
||||
componentWillAppear (done) {
|
||||
if (animUtil.isAppearSupported(this.props)) {
|
||||
this.transition('appear', done)
|
||||
} else {
|
||||
done()
|
||||
}
|
||||
}
|
||||
|
||||
componentWillLeave (done) {
|
||||
if (animUtil.isLeaveSupported(this.props)) {
|
||||
this.transition('leave', done)
|
||||
} else {
|
||||
// always sync, do not interupt with react component life cycle
|
||||
// update hidden -> animate hidden ->
|
||||
// didUpdate -> animate leave -> unmount (if animate is none)
|
||||
done()
|
||||
}
|
||||
}
|
||||
|
||||
transition (animationType, finishCallback) {
|
||||
const node = ReactDOM.findDOMNode(this)
|
||||
const props = this.props
|
||||
const transitionName = props.transitionName
|
||||
const nameIsObj = typeof transitionName === 'object'
|
||||
this.stop()
|
||||
const end = () => {
|
||||
this.stopper = null
|
||||
finishCallback()
|
||||
}
|
||||
if ((isCssAnimationSupported || !props.animation[animationType]) &&
|
||||
transitionName && props[transitionMap[animationType]]) {
|
||||
const name = nameIsObj ? transitionName[animationType] : `${transitionName}-${animationType}`
|
||||
let activeName = `${name}-active`
|
||||
if (nameIsObj && transitionName[`${animationType}Active`]) {
|
||||
activeName = transitionName[`${animationType}Active`]
|
||||
}
|
||||
this.stopper = cssAnimate(node, {
|
||||
name,
|
||||
active: activeName,
|
||||
}, end)
|
||||
} else {
|
||||
this.stopper = props.animation[animationType](node, end)
|
||||
}
|
||||
}
|
||||
|
||||
stop () {
|
||||
const stopper = this.stopper
|
||||
if (stopper) {
|
||||
this.stopper = null
|
||||
stopper.stop()
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
return this.props.children
|
||||
}
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
import React from 'react'
|
||||
|
||||
export function toArrayChildren (children) {
|
||||
const ret = []
|
||||
React.Children.forEach(children, (child) => {
|
||||
ret.push(child)
|
||||
})
|
||||
return ret
|
||||
}
|
||||
|
||||
export function findChildInChildrenByKey (children, key) {
|
||||
let ret = null
|
||||
if (children) {
|
||||
children.forEach((child) => {
|
||||
if (ret) {
|
||||
return
|
||||
}
|
||||
if (child && child.key === key) {
|
||||
ret = child
|
||||
}
|
||||
})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
export function findShownChildInChildrenByKey (children, key, showProp) {
|
||||
let ret = null
|
||||
if (children) {
|
||||
children.forEach((child) => {
|
||||
if (child && child.key === key && child.props[showProp]) {
|
||||
if (ret) {
|
||||
throw new Error('two child with same key for <rc-animate> children')
|
||||
}
|
||||
ret = child
|
||||
}
|
||||
})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
export function findHiddenChildInChildrenByKey (children, key, showProp) {
|
||||
let found = 0
|
||||
if (children) {
|
||||
children.forEach((child) => {
|
||||
if (found) {
|
||||
return
|
||||
}
|
||||
found = child && child.key === key && !child.props[showProp]
|
||||
})
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
||||
export function isSameChildren (c1, c2, showProp) {
|
||||
let same = c1.length === c2.length
|
||||
if (same) {
|
||||
c1.forEach((child, index) => {
|
||||
const child2 = c2[index]
|
||||
if (child && child2) {
|
||||
if ((child && !child2) || (!child && child2)) {
|
||||
same = false
|
||||
} else if (child.key !== child2.key) {
|
||||
same = false
|
||||
} else if (showProp && child.props[showProp] !== child2.props[showProp]) {
|
||||
same = false
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return same
|
||||
}
|
||||
|
||||
export function mergeChildren (prev, next) {
|
||||
let ret = []
|
||||
|
||||
// For each key of `next`, the list of keys to insert before that key in
|
||||
// the combined list
|
||||
const nextChildrenPending = {}
|
||||
let pendingChildren = []
|
||||
prev.forEach((child) => {
|
||||
if (child && findChildInChildrenByKey(next, child.key)) {
|
||||
if (pendingChildren.length) {
|
||||
nextChildrenPending[child.key] = pendingChildren
|
||||
pendingChildren = []
|
||||
}
|
||||
} else {
|
||||
pendingChildren.push(child)
|
||||
}
|
||||
})
|
||||
|
||||
next.forEach((child) => {
|
||||
if (child && nextChildrenPending.hasOwnProperty(child.key)) {
|
||||
ret = ret.concat(nextChildrenPending[child.key])
|
||||
}
|
||||
ret.push(child)
|
||||
})
|
||||
|
||||
ret = ret.concat(pendingChildren)
|
||||
|
||||
return ret
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
const util = {
|
||||
isAppearSupported(props) {
|
||||
return props.transitionName && props.transitionAppear || props.animation.appear;
|
||||
},
|
||||
isEnterSupported(props) {
|
||||
return props.transitionName && props.transitionEnter || props.animation.enter;
|
||||
},
|
||||
isLeaveSupported(props) {
|
||||
return props.transitionName && props.transitionLeave || props.animation.leave;
|
||||
},
|
||||
allowAppearCallback(props) {
|
||||
return props.transitionAppear || props.animation.appear;
|
||||
},
|
||||
allowEnterCallback(props) {
|
||||
return props.transitionEnter || props.animation.enter;
|
||||
},
|
||||
allowLeaveCallback(props) {
|
||||
return props.transitionLeave || props.animation.leave;
|
||||
},
|
||||
};
|
||||
export default util;
|
|
@ -1,5 +1,3 @@
|
|||
import React from 'react'
|
||||
|
||||
export function noop () {
|
||||
}
|
||||
|
||||
|
@ -9,18 +7,18 @@ export function getKeyFromChildrenIndex (child, menuEventKey, index) {
|
|||
}
|
||||
|
||||
export function loopMenuItem (children, cb) {
|
||||
let index = -1
|
||||
React.Children.forEach(children, (c) => {
|
||||
index++
|
||||
if (c && c.type && c.type.isMenuItemGroup) {
|
||||
React.Children.forEach(c.props.children, (c2) => {
|
||||
index++
|
||||
cb(c2, index)
|
||||
})
|
||||
} else {
|
||||
cb(c, index)
|
||||
}
|
||||
})
|
||||
// let index = -1
|
||||
// React.Children.forEach(children, (c) => {
|
||||
// index++
|
||||
// if (c && c.type && c.type.isMenuItemGroup) {
|
||||
// React.Children.forEach(c.props.children, (c2) => {
|
||||
// index++
|
||||
// cb(c2, index)
|
||||
// })
|
||||
// } else {
|
||||
// cb(c, index)
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
export function loopMenuItemRecusively (children, keys, ret) {
|
||||
|
|
|
@ -77,6 +77,7 @@
|
|||
"add-dom-event-listener": "^1.0.2",
|
||||
"css-animation": "^1.4.1",
|
||||
"eslint-plugin-vue": "^3.13.0",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"omit.js": "^1.0.0",
|
||||
"vue-types": "^1.0.2",
|
||||
|
|
Loading…
Reference in New Issue