Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/assets/javascripts/vue-virtual-scroller/src/components/DynamicScroller.vue')
-rw-r--r--vendor/assets/javascripts/vue-virtual-scroller/src/components/DynamicScroller.vue212
1 files changed, 212 insertions, 0 deletions
diff --git a/vendor/assets/javascripts/vue-virtual-scroller/src/components/DynamicScroller.vue b/vendor/assets/javascripts/vue-virtual-scroller/src/components/DynamicScroller.vue
new file mode 100644
index 00000000000..e9f3acea9d8
--- /dev/null
+++ b/vendor/assets/javascripts/vue-virtual-scroller/src/components/DynamicScroller.vue
@@ -0,0 +1,212 @@
+<template>
+ <RecycleScroller
+ ref="scroller"
+ :items="itemsWithSize"
+ :min-item-size="minItemSize"
+ :direction="direction"
+ key-field="id"
+ v-bind="$attrs"
+ @resize="onScrollerResize"
+ @visible="onScrollerVisible"
+ v-on="listeners"
+ >
+ <template slot-scope="{ item: itemWithSize, index, active }">
+ <slot
+ v-bind="{
+ item: itemWithSize.item,
+ index,
+ active,
+ itemWithSize
+ }"
+ />
+ </template>
+ <template slot="before">
+ <slot name="before" />
+ </template>
+ <template slot="after">
+ <slot name="after" />
+ </template>
+ </RecycleScroller>
+</template>
+
+<script>
+import RecycleScroller from './RecycleScroller.vue'
+import { props, simpleArray } from './common'
+
+export default {
+ name: 'DynamicScroller',
+
+ components: {
+ RecycleScroller,
+ },
+
+ inheritAttrs: false,
+
+ provide () {
+ if (typeof ResizeObserver !== 'undefined') {
+ this.$_resizeObserver = new ResizeObserver(entries => {
+ for (const entry of entries) {
+ if (entry.target) {
+ const event = new CustomEvent(
+ 'resize',
+ {
+ detail: {
+ contentRect: entry.contentRect,
+ },
+ },
+ )
+ entry.target.dispatchEvent(event)
+ }
+ }
+ })
+ }
+
+ return {
+ vscrollData: this.vscrollData,
+ vscrollParent: this,
+ vscrollResizeObserver: this.$_resizeObserver,
+ }
+ },
+
+ props: {
+ ...props,
+
+ minItemSize: {
+ type: [Number, String],
+ required: true,
+ },
+ },
+
+ data () {
+ return {
+ vscrollData: {
+ active: true,
+ sizes: {},
+ validSizes: {},
+ keyField: this.keyField,
+ simpleArray: false,
+ },
+ }
+ },
+
+ computed: {
+ simpleArray,
+
+ itemsWithSize () {
+ const result = []
+ const { items, keyField, simpleArray } = this
+ const sizes = this.vscrollData.sizes
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i]
+ const id = simpleArray ? i : item[keyField]
+ let size = sizes[id]
+ if (typeof size === 'undefined' && !this.$_undefinedMap[id]) {
+ size = 0
+ }
+ result.push({
+ item,
+ id,
+ size,
+ })
+ }
+ return result
+ },
+
+ listeners () {
+ const listeners = {}
+ for (const key in this.$listeners) {
+ if (key !== 'resize' && key !== 'visible') {
+ listeners[key] = this.$listeners[key]
+ }
+ }
+ return listeners
+ },
+ },
+
+ watch: {
+ items () {
+ this.forceUpdate(false)
+ },
+
+ simpleArray: {
+ handler (value) {
+ this.vscrollData.simpleArray = value
+ },
+ immediate: true,
+ },
+
+ direction (value) {
+ this.forceUpdate(true)
+ },
+ },
+
+ created () {
+ this.$_updates = []
+ this.$_undefinedSizes = 0
+ this.$_undefinedMap = {}
+ },
+
+ activated () {
+ this.vscrollData.active = true
+ },
+
+ deactivated () {
+ this.vscrollData.active = false
+ },
+
+ methods: {
+ onScrollerResize () {
+ const scroller = this.$refs.scroller
+ if (scroller) {
+ this.forceUpdate()
+ }
+ this.$emit('resize')
+ },
+
+ onScrollerVisible () {
+ this.$emit('vscroll:update', { force: false })
+ this.$emit('visible')
+ },
+
+ forceUpdate (clear = true) {
+ if (clear || this.simpleArray) {
+ this.vscrollData.validSizes = {}
+ }
+ this.$emit('vscroll:update', { force: true })
+ },
+
+ scrollToItem (index) {
+ const scroller = this.$refs.scroller
+ if (scroller) scroller.scrollToItem(index)
+ },
+
+ getItemSize (item, index = undefined) {
+ const id = this.simpleArray ? (index != null ? index : this.items.indexOf(item)) : item[this.keyField]
+ return this.vscrollData.sizes[id] || 0
+ },
+
+ scrollToBottom () {
+ if (this.$_scrollingToBottom) return
+ this.$_scrollingToBottom = true
+ const el = this.$el
+ // Item is inserted to the DOM
+ this.$nextTick(() => {
+ el.scrollTop = el.scrollHeight + 5000
+ // Item sizes are computed
+ const cb = () => {
+ el.scrollTop = el.scrollHeight + 5000
+ requestAnimationFrame(() => {
+ el.scrollTop = el.scrollHeight + 5000
+ if (this.$_undefinedSizes === 0) {
+ this.$_scrollingToBottom = false
+ } else {
+ requestAnimationFrame(cb)
+ }
+ })
+ }
+ requestAnimationFrame(cb)
+ })
+ },
+ },
+}
+</script>