1import Vue from 'vue'
2import { ItemProps, SlotProps } from './props'
3
4const Wrapper = {
5  created() {
6    this.shapeKey = this.horizontal ? 'offsetWidth' : 'offsetHeight'
7  },
8
9  mounted() {
10    if (typeof ResizeObserver !== 'undefined') {
11      this.resizeObserver = new ResizeObserver(() => {
12        this.dispatchSizeChange()
13      })
14      this.resizeObserver.observe(this.$el)
15    }
16  },
17
18  // since component will be reused, so dispatch when updated
19  updated() {
20    this.dispatchSizeChange()
21  },
22
23  beforeDestroy() {
24    if (this.resizeObserver) {
25      this.resizeObserver.disconnect()
26      this.resizeObserver = null
27    }
28  },
29
30  methods: {
31    getCurrentSize() {
32      return this.$el ? this.$el[this.shapeKey] : 0
33    },
34
35    // tell parent current size identify by unique key
36    dispatchSizeChange() {
37      this.$parent.$emit(this.event, this.uniqueKey, this.getCurrentSize(), this.hasInitial)
38    }
39  }
40}
41
42// wrapping for item
43export const Item = Vue.component('virtual-list-item', {
44  mixins: [Wrapper],
45
46  props: ItemProps,
47
48  render(h) {
49    const { tag, component, extraProps = {}, index, scopedSlots = {}, uniqueKey } = this
50    extraProps.source = this.source
51    extraProps.index = index
52
53    return h(tag, {
54      key: uniqueKey,
55      attrs: {
56        role: 'item'
57      }
58    }, [h(component, {
59      props: extraProps,
60      scopedSlots: scopedSlots
61    })])
62  }
63})
64
65// wrapping for slot
66export const Slot = Vue.component('virtual-list-slot', {
67  mixins: [Wrapper],
68
69  props: SlotProps,
70
71  render(h) {
72    const { tag, uniqueKey } = this
73
74    return h(tag, {
75      key: uniqueKey,
76      attrs: {
77        role: uniqueKey
78      }
79    }, this.$slots.default)
80  }
81})