import { warn, extend } from 'core/util/index' 
 | 
import { transitionProps, extractTransitionData } from './transition' 
 | 
  
 | 
const props = extend({ 
 | 
  tag: String, 
 | 
  moveClass: String 
 | 
}, transitionProps) 
 | 
  
 | 
delete props.mode 
 | 
  
 | 
export default { 
 | 
  props, 
 | 
  
 | 
  created () { 
 | 
    const dom = this.$requireWeexModule('dom') 
 | 
    this.getPosition = el => new Promise((resolve, reject) => { 
 | 
      dom.getComponentRect(el.ref, res => { 
 | 
        if (!res.result) { 
 | 
          reject(new Error(`failed to get rect for element: ${el.tag}`)) 
 | 
        } else { 
 | 
          resolve(res.size) 
 | 
        } 
 | 
      }) 
 | 
    }) 
 | 
  
 | 
    const animation = this.$requireWeexModule('animation') 
 | 
    this.animate = (el, options) => new Promise(resolve => { 
 | 
      animation.transition(el.ref, options, resolve) 
 | 
    }) 
 | 
  }, 
 | 
  
 | 
  render (h) { 
 | 
    const tag = this.tag || this.$vnode.data.tag || 'span' 
 | 
    const map = Object.create(null) 
 | 
    const prevChildren = this.prevChildren = this.children 
 | 
    const rawChildren = this.$slots.default || [] 
 | 
    const children = this.children = [] 
 | 
    const transitionData = extractTransitionData(this) 
 | 
  
 | 
    for (let i = 0; i < rawChildren.length; i++) { 
 | 
      const c = rawChildren[i] 
 | 
      if (c.tag) { 
 | 
        if (c.key != null && String(c.key).indexOf('__vlist') !== 0) { 
 | 
          children.push(c) 
 | 
          map[c.key] = c 
 | 
          ;(c.data || (c.data = {})).transition = transitionData 
 | 
        } else if (process.env.NODE_ENV !== 'production') { 
 | 
          const opts = c.componentOptions 
 | 
          const name = opts 
 | 
            ? (opts.Ctor.options.name || opts.tag) 
 | 
            : c.tag 
 | 
          warn(`<transition-group> children must be keyed: <${name}>`) 
 | 
        } 
 | 
      } 
 | 
    } 
 | 
  
 | 
    if (prevChildren) { 
 | 
      const kept = [] 
 | 
      const removed = [] 
 | 
      prevChildren.forEach(c => { 
 | 
        c.data.transition = transitionData 
 | 
  
 | 
        // TODO: record before patch positions 
 | 
  
 | 
        if (map[c.key]) { 
 | 
          kept.push(c) 
 | 
        } else { 
 | 
          removed.push(c) 
 | 
        } 
 | 
      }) 
 | 
      this.kept = h(tag, null, kept) 
 | 
      this.removed = removed 
 | 
    } 
 | 
  
 | 
    return h(tag, null, children) 
 | 
  }, 
 | 
  
 | 
  beforeUpdate () { 
 | 
    // force removing pass 
 | 
    this.__patch__( 
 | 
      this._vnode, 
 | 
      this.kept, 
 | 
      false, // hydrating 
 | 
      true // removeOnly (!important, avoids unnecessary moves) 
 | 
    ) 
 | 
    this._vnode = this.kept 
 | 
  }, 
 | 
  
 | 
  updated () { 
 | 
    const children = this.prevChildren 
 | 
    const moveClass = this.moveClass || ((this.name || 'v') + '-move') 
 | 
    const moveData = children.length && this.getMoveData(children[0].context, moveClass) 
 | 
    if (!moveData) { 
 | 
      return 
 | 
    } 
 | 
  
 | 
    // TODO: finish implementing move animations once 
 | 
    // we have access to sync getComponentRect() 
 | 
  
 | 
    // children.forEach(callPendingCbs) 
 | 
  
 | 
    // Promise.all(children.map(c => { 
 | 
    //   const oldPos = c.data.pos 
 | 
    //   const newPos = c.data.newPos 
 | 
    //   const dx = oldPos.left - newPos.left 
 | 
    //   const dy = oldPos.top - newPos.top 
 | 
    //   if (dx || dy) { 
 | 
    //     c.data.moved = true 
 | 
    //     return this.animate(c.elm, { 
 | 
    //       styles: { 
 | 
    //         transform: `translate(${dx}px,${dy}px)` 
 | 
    //       } 
 | 
    //     }) 
 | 
    //   } 
 | 
    // })).then(() => { 
 | 
    //   children.forEach(c => { 
 | 
    //     if (c.data.moved) { 
 | 
    //       this.animate(c.elm, { 
 | 
    //         styles: { 
 | 
    //           transform: '' 
 | 
    //         }, 
 | 
    //         duration: moveData.duration || 0, 
 | 
    //         delay: moveData.delay || 0, 
 | 
    //         timingFunction: moveData.timingFunction || 'linear' 
 | 
    //       }) 
 | 
    //     } 
 | 
    //   }) 
 | 
    // }) 
 | 
  }, 
 | 
  
 | 
  methods: { 
 | 
    getMoveData (context, moveClass) { 
 | 
      const stylesheet = context.$options.style || {} 
 | 
      return stylesheet['@TRANSITION'] && stylesheet['@TRANSITION'][moveClass] 
 | 
    } 
 | 
  } 
 | 
} 
 | 
  
 | 
// function callPendingCbs (c) { 
 | 
//   /* istanbul ignore if */ 
 | 
//   if (c.elm._moveCb) { 
 | 
//     c.elm._moveCb() 
 | 
//   } 
 | 
//   /* istanbul ignore if */ 
 | 
//   if (c.elm._enterCb) { 
 | 
//     c.elm._enterCb() 
 | 
//   } 
 | 
// } 
 |