fix: maintain scroll position in ListRows component
This commit is contained in:
parent
3dc45c3c8c
commit
d1efa543db
@ -11,7 +11,10 @@
|
|||||||
row-key="name"
|
row-key="name"
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
>
|
>
|
||||||
<ListHeader class="sm:mx-5 mx-3" @columnWidthUpdated="emit('columnWidthUpdated')">
|
<ListHeader
|
||||||
|
class="sm:mx-5 mx-3"
|
||||||
|
@columnWidthUpdated="emit('columnWidthUpdated')"
|
||||||
|
>
|
||||||
<ListHeaderItem
|
<ListHeaderItem
|
||||||
v-for="column in columns"
|
v-for="column in columns"
|
||||||
:key="column.key"
|
:key="column.key"
|
||||||
@ -29,12 +32,11 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</ListHeaderItem>
|
</ListHeaderItem>
|
||||||
</ListHeader>
|
</ListHeader>
|
||||||
<ListRows class="mx-3 sm:mx-5" id="list-rows">
|
<ListRows
|
||||||
<ListRow
|
class="mx-3 sm:mx-5"
|
||||||
v-for="row in rows"
|
:rows="rows"
|
||||||
:key="row.name"
|
|
||||||
v-slot="{ idx, column, item }"
|
v-slot="{ idx, column, item }"
|
||||||
:row="row"
|
doctype="CRM Call Log"
|
||||||
>
|
>
|
||||||
<ListRowItem :item="item">
|
<ListRowItem :item="item">
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
@ -102,8 +104,7 @@
|
|||||||
variant="ghosted"
|
variant="ghosted"
|
||||||
:class="isLiked(item) ? 'fill-red-500' : 'fill-white'"
|
:class="isLiked(item) ? 'fill-red-500' : 'fill-white'"
|
||||||
@click.stop.prevent="
|
@click.stop.prevent="
|
||||||
() =>
|
() => emit('likeDoc', { name: row.name, liked: isLiked(item) })
|
||||||
emit('likeDoc', { name: row.name, liked: isLiked(item) })
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<HeartIcon class="h-4 w-4" />
|
<HeartIcon class="h-4 w-4" />
|
||||||
@ -127,7 +128,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</ListRowItem>
|
</ListRowItem>
|
||||||
</ListRow>
|
|
||||||
</ListRows>
|
</ListRows>
|
||||||
<ListSelectBanner>
|
<ListSelectBanner>
|
||||||
<template #actions="{ selections, unselectAll }">
|
<template #actions="{ selections, unselectAll }">
|
||||||
@ -161,13 +161,12 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import HeartIcon from '@/components/Icons/HeartIcon.vue'
|
import HeartIcon from '@/components/Icons/HeartIcon.vue'
|
||||||
import ListBulkActions from '@/components/ListBulkActions.vue'
|
import ListBulkActions from '@/components/ListBulkActions.vue'
|
||||||
|
import ListRows from '@/components/ListViews/ListRows.vue'
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
ListView,
|
ListView,
|
||||||
ListHeader,
|
ListHeader,
|
||||||
ListHeaderItem,
|
ListHeaderItem,
|
||||||
ListRows,
|
|
||||||
ListRow,
|
|
||||||
ListSelectBanner,
|
ListSelectBanner,
|
||||||
ListRowItem,
|
ListRowItem,
|
||||||
ListFooter,
|
ListFooter,
|
||||||
@ -232,7 +231,7 @@ const listBulkActionsRef = ref(null)
|
|||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
customListActions: computed(
|
customListActions: computed(
|
||||||
() => listBulkActionsRef.value?.customListActions
|
() => listBulkActionsRef.value?.customListActions,
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -36,12 +36,11 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</ListHeaderItem>
|
</ListHeaderItem>
|
||||||
</ListHeader>
|
</ListHeader>
|
||||||
<ListRows class="mx-3 sm:mx-5" id="list-rows">
|
<ListRows
|
||||||
<ListRow
|
class="mx-3 sm:mx-5"
|
||||||
v-for="row in rows"
|
:rows="rows"
|
||||||
:key="row.name"
|
|
||||||
v-slot="{ idx, column, item }"
|
v-slot="{ idx, column, item }"
|
||||||
:row="row"
|
doctype="Contact"
|
||||||
>
|
>
|
||||||
<ListRowItem :item="item">
|
<ListRowItem :item="item">
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
@ -100,8 +99,7 @@
|
|||||||
variant="ghosted"
|
variant="ghosted"
|
||||||
:class="isLiked(item) ? 'fill-red-500' : 'fill-white'"
|
:class="isLiked(item) ? 'fill-red-500' : 'fill-white'"
|
||||||
@click.stop.prevent="
|
@click.stop.prevent="
|
||||||
() =>
|
() => emit('likeDoc', { name: row.name, liked: isLiked(item) })
|
||||||
emit('likeDoc', { name: row.name, liked: isLiked(item) })
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<HeartIcon class="h-4 w-4" />
|
<HeartIcon class="h-4 w-4" />
|
||||||
@ -125,7 +123,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</ListRowItem>
|
</ListRowItem>
|
||||||
</ListRow>
|
|
||||||
</ListRows>
|
</ListRows>
|
||||||
<ListSelectBanner>
|
<ListSelectBanner>
|
||||||
<template #actions="{ selections, unselectAll }">
|
<template #actions="{ selections, unselectAll }">
|
||||||
@ -160,13 +157,12 @@
|
|||||||
import HeartIcon from '@/components/Icons/HeartIcon.vue'
|
import HeartIcon from '@/components/Icons/HeartIcon.vue'
|
||||||
import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
|
import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
|
||||||
import ListBulkActions from '@/components/ListBulkActions.vue'
|
import ListBulkActions from '@/components/ListBulkActions.vue'
|
||||||
|
import ListRows from '@/components/ListViews/ListRows.vue'
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
ListView,
|
ListView,
|
||||||
ListHeader,
|
ListHeader,
|
||||||
ListHeaderItem,
|
ListHeaderItem,
|
||||||
ListRows,
|
|
||||||
ListRow,
|
|
||||||
ListSelectBanner,
|
ListSelectBanner,
|
||||||
ListRowItem,
|
ListRowItem,
|
||||||
ListFooter,
|
ListFooter,
|
||||||
|
|||||||
@ -36,7 +36,11 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</ListHeaderItem>
|
</ListHeaderItem>
|
||||||
</ListHeader>
|
</ListHeader>
|
||||||
<ListRows :rows="rows" v-slot="{ idx, column, item, row }">
|
<ListRows
|
||||||
|
:rows="rows"
|
||||||
|
v-slot="{ idx, column, item, row }"
|
||||||
|
doctype="CRM Deal"
|
||||||
|
>
|
||||||
<div v-if="column.key === '_assign'" class="flex items-center">
|
<div v-if="column.key === '_assign'" class="flex items-center">
|
||||||
<MultipleAvatar
|
<MultipleAvatar
|
||||||
:avatars="item"
|
:avatars="item"
|
||||||
|
|||||||
@ -10,7 +10,10 @@
|
|||||||
}"
|
}"
|
||||||
row-key="name"
|
row-key="name"
|
||||||
>
|
>
|
||||||
<ListHeader class="sm:mx-5 mx-3" @columnWidthUpdated="emit('columnWidthUpdated')">
|
<ListHeader
|
||||||
|
class="sm:mx-5 mx-3"
|
||||||
|
@columnWidthUpdated="emit('columnWidthUpdated')"
|
||||||
|
>
|
||||||
<ListHeaderItem
|
<ListHeaderItem
|
||||||
v-for="column in columns"
|
v-for="column in columns"
|
||||||
:key="column.key"
|
:key="column.key"
|
||||||
@ -28,12 +31,11 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</ListHeaderItem>
|
</ListHeaderItem>
|
||||||
</ListHeader>
|
</ListHeader>
|
||||||
<ListRows class="mx-3 sm:mx-5" id="list-rows">
|
<ListRows
|
||||||
<ListRow
|
class="mx-3 sm:mx-5"
|
||||||
v-for="row in rows"
|
:rows="rows"
|
||||||
:key="row.name"
|
|
||||||
v-slot="{ idx, column, item }"
|
v-slot="{ idx, column, item }"
|
||||||
:row="row"
|
doctype="Email Template"
|
||||||
>
|
>
|
||||||
<ListRowItem :item="item">
|
<ListRowItem :item="item">
|
||||||
<!-- <template #prefix>
|
<!-- <template #prefix>
|
||||||
@ -90,8 +92,7 @@
|
|||||||
variant="ghosted"
|
variant="ghosted"
|
||||||
:class="isLiked(item) ? 'fill-red-500' : 'fill-white'"
|
:class="isLiked(item) ? 'fill-red-500' : 'fill-white'"
|
||||||
@click.stop.prevent="
|
@click.stop.prevent="
|
||||||
() =>
|
() => emit('likeDoc', { name: row.name, liked: isLiked(item) })
|
||||||
emit('likeDoc', { name: row.name, liked: isLiked(item) })
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<HeartIcon class="h-4 w-4" />
|
<HeartIcon class="h-4 w-4" />
|
||||||
@ -115,7 +116,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</ListRowItem>
|
</ListRowItem>
|
||||||
</ListRow>
|
|
||||||
</ListRows>
|
</ListRows>
|
||||||
<ListSelectBanner>
|
<ListSelectBanner>
|
||||||
<template #actions="{ selections, unselectAll }">
|
<template #actions="{ selections, unselectAll }">
|
||||||
@ -148,12 +148,11 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import HeartIcon from '@/components/Icons/HeartIcon.vue'
|
import HeartIcon from '@/components/Icons/HeartIcon.vue'
|
||||||
import ListBulkActions from '@/components/ListBulkActions.vue'
|
import ListBulkActions from '@/components/ListBulkActions.vue'
|
||||||
|
import ListRows from '@/components/ListViews/ListRows.vue'
|
||||||
import {
|
import {
|
||||||
ListView,
|
ListView,
|
||||||
ListHeader,
|
ListHeader,
|
||||||
ListHeaderItem,
|
ListHeaderItem,
|
||||||
ListRows,
|
|
||||||
ListRow,
|
|
||||||
ListSelectBanner,
|
ListSelectBanner,
|
||||||
ListRowItem,
|
ListRowItem,
|
||||||
ListFooter,
|
ListFooter,
|
||||||
@ -219,7 +218,7 @@ const listBulkActionsRef = ref(null)
|
|||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
customListActions: computed(
|
customListActions: computed(
|
||||||
() => listBulkActionsRef.value?.customListActions
|
() => listBulkActionsRef.value?.customListActions,
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -36,7 +36,11 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</ListHeaderItem>
|
</ListHeaderItem>
|
||||||
</ListHeader>
|
</ListHeader>
|
||||||
<ListRows :rows="rows" v-slot="{ idx, column, item, row }">
|
<ListRows
|
||||||
|
:rows="rows"
|
||||||
|
v-slot="{ idx, column, item, row }"
|
||||||
|
doctype="CRM Lead"
|
||||||
|
>
|
||||||
<div v-if="column.key === '_assign'" class="flex items-center">
|
<div v-if="column.key === '_assign'" class="flex items-center">
|
||||||
<MultipleAvatar
|
<MultipleAvatar
|
||||||
:avatars="item"
|
:avatars="item"
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ListGroupHeader>
|
</ListGroupHeader>
|
||||||
<ListGroupRows :group="group" id="list-rows">
|
<ListGroupRows :group="group">
|
||||||
<ListRow
|
<ListRow
|
||||||
v-for="row in group.rows"
|
v-for="row in group.rows"
|
||||||
:key="row.name"
|
:key="row.name"
|
||||||
@ -27,7 +27,12 @@
|
|||||||
</ListGroupRows>
|
</ListGroupRows>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ListRows class="mx-3 sm:mx-5" v-else id="list-rows">
|
<ListRows
|
||||||
|
v-else
|
||||||
|
ref="scrollContainer"
|
||||||
|
class="mx-3 sm:mx-5"
|
||||||
|
@scroll="handleScroll"
|
||||||
|
>
|
||||||
<ListRow
|
<ListRow
|
||||||
v-for="row in reactivieRows"
|
v-for="row in reactivieRows"
|
||||||
:key="row.name"
|
:key="row.name"
|
||||||
@ -40,27 +45,53 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { useStorage } from '@vueuse/core'
|
||||||
import { ListRows, ListRow, ListGroupHeader, ListGroupRows } from 'frappe-ui'
|
import { ListRows, ListRow, ListGroupHeader, ListGroupRows } from 'frappe-ui'
|
||||||
|
import { ref, computed, watch, onBeforeUnmount, onMounted } from 'vue'
|
||||||
import { ref, computed, watch } from 'vue'
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
rows: {
|
rows: {
|
||||||
type: Array,
|
type: Array,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
doctype: {
|
||||||
|
type: String,
|
||||||
|
default: 'CRM Lead',
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const reactivieRows = ref(props.rows)
|
const reactivieRows = ref(props.rows)
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.rows,
|
() => props.rows,
|
||||||
(val) => (reactivieRows.value = val)
|
(val) => (reactivieRows.value = val),
|
||||||
)
|
)
|
||||||
|
|
||||||
let showGroupedRows = computed(() => {
|
let showGroupedRows = computed(() => {
|
||||||
return props.rows.every(
|
return props.rows.every(
|
||||||
(row) => row.group && row.rows && Array.isArray(row.rows)
|
(row) => row.group && row.rows && Array.isArray(row.rows),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const scrollPosition = useStorage(`scrollPosition${props.doctype}`, 0)
|
||||||
|
const scrollContainer = ref(null)
|
||||||
|
|
||||||
|
const handleScroll = () => {
|
||||||
|
if (scrollContainer.value) {
|
||||||
|
scrollPosition.value = scrollContainer.value.$el.scrollTop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
if (scrollContainer.value) {
|
||||||
|
scrollContainer.value.$el.removeEventListener('scroll', handleScroll)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (scrollContainer.value) {
|
||||||
|
scrollContainer.value.$el.addEventListener('scroll', handleScroll)
|
||||||
|
scrollContainer.value.$el.scrollTop = scrollPosition.value
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -14,7 +14,10 @@
|
|||||||
}"
|
}"
|
||||||
row-key="name"
|
row-key="name"
|
||||||
>
|
>
|
||||||
<ListHeader class="sm:mx-5 mx-3" @columnWidthUpdated="emit('columnWidthUpdated')">
|
<ListHeader
|
||||||
|
class="sm:mx-5 mx-3"
|
||||||
|
@columnWidthUpdated="emit('columnWidthUpdated')"
|
||||||
|
>
|
||||||
<ListHeaderItem
|
<ListHeaderItem
|
||||||
v-for="column in columns"
|
v-for="column in columns"
|
||||||
:key="column.key"
|
:key="column.key"
|
||||||
@ -32,12 +35,11 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</ListHeaderItem>
|
</ListHeaderItem>
|
||||||
</ListHeader>
|
</ListHeader>
|
||||||
<ListRows class="mx-3 sm:mx-5" id="list-rows">
|
<ListRows
|
||||||
<ListRow
|
class="mx-3 sm:mx-5"
|
||||||
v-for="row in rows"
|
:rows="rows"
|
||||||
:key="row.name"
|
|
||||||
v-slot="{ idx, column, item }"
|
v-slot="{ idx, column, item }"
|
||||||
:row="row"
|
doctype="CRM Organization"
|
||||||
>
|
>
|
||||||
<ListRowItem :item="item">
|
<ListRowItem :item="item">
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
@ -84,8 +86,7 @@
|
|||||||
variant="ghosted"
|
variant="ghosted"
|
||||||
:class="isLiked(item) ? 'fill-red-500' : 'fill-white'"
|
:class="isLiked(item) ? 'fill-red-500' : 'fill-white'"
|
||||||
@click.stop.prevent="
|
@click.stop.prevent="
|
||||||
() =>
|
() => emit('likeDoc', { name: row.name, liked: isLiked(item) })
|
||||||
emit('likeDoc', { name: row.name, liked: isLiked(item) })
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<HeartIcon class="h-4 w-4" />
|
<HeartIcon class="h-4 w-4" />
|
||||||
@ -109,7 +110,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</ListRowItem>
|
</ListRowItem>
|
||||||
</ListRow>
|
|
||||||
</ListRows>
|
</ListRows>
|
||||||
<ListSelectBanner>
|
<ListSelectBanner>
|
||||||
<template #actions="{ selections, unselectAll }">
|
<template #actions="{ selections, unselectAll }">
|
||||||
@ -142,13 +142,12 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import HeartIcon from '@/components/Icons/HeartIcon.vue'
|
import HeartIcon from '@/components/Icons/HeartIcon.vue'
|
||||||
import ListBulkActions from '@/components/ListBulkActions.vue'
|
import ListBulkActions from '@/components/ListBulkActions.vue'
|
||||||
|
import ListRows from '@/components/ListViews/ListRows.vue'
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
ListView,
|
ListView,
|
||||||
ListHeader,
|
ListHeader,
|
||||||
ListHeaderItem,
|
ListHeaderItem,
|
||||||
ListRows,
|
|
||||||
ListRow,
|
|
||||||
ListSelectBanner,
|
ListSelectBanner,
|
||||||
ListRowItem,
|
ListRowItem,
|
||||||
ListFooter,
|
ListFooter,
|
||||||
@ -216,7 +215,7 @@ const listBulkActionsRef = ref(null)
|
|||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
customListActions: computed(
|
customListActions: computed(
|
||||||
() => listBulkActionsRef.value?.customListActions
|
() => listBulkActionsRef.value?.customListActions,
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -31,17 +31,14 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</ListHeaderItem>
|
</ListHeaderItem>
|
||||||
</ListHeader>
|
</ListHeader>
|
||||||
<ListRows class="mx-3 sm:mx-5" id="list-rows">
|
<ListRows
|
||||||
<ListRow
|
class="mx-3 sm:mx-5"
|
||||||
v-for="row in rows"
|
:rows="rows"
|
||||||
:key="row.name"
|
|
||||||
v-slot="{ idx, column, item }"
|
v-slot="{ idx, column, item }"
|
||||||
:row="row"
|
doctype="CRM Task"
|
||||||
>
|
>
|
||||||
<div v-if="column.key === 'due_date'">
|
<div v-if="column.key === 'due_date'">
|
||||||
<Tooltip
|
<Tooltip :text="item && formatDate(item, 'ddd, MMM D, YYYY | hh:mm a')">
|
||||||
:text="item && formatDate(item, 'ddd, MMM D, YYYY | hh:mm a')"
|
|
||||||
>
|
|
||||||
<div class="flex items-center gap-2 truncate text-base">
|
<div class="flex items-center gap-2 truncate text-base">
|
||||||
<div><CalendarIcon /></div>
|
<div><CalendarIcon /></div>
|
||||||
<div v-if="item" class="truncate">
|
<div v-if="item" class="truncate">
|
||||||
@ -106,8 +103,7 @@
|
|||||||
variant="ghosted"
|
variant="ghosted"
|
||||||
:class="isLiked(item) ? 'fill-red-500' : 'fill-white'"
|
:class="isLiked(item) ? 'fill-red-500' : 'fill-white'"
|
||||||
@click.stop.prevent="
|
@click.stop.prevent="
|
||||||
() =>
|
() => emit('likeDoc', { name: row.name, liked: isLiked(item) })
|
||||||
emit('likeDoc', { name: row.name, liked: isLiked(item) })
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<HeartIcon class="h-4 w-4" />
|
<HeartIcon class="h-4 w-4" />
|
||||||
@ -131,7 +127,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</ListRowItem>
|
</ListRowItem>
|
||||||
</ListRow>
|
|
||||||
</ListRows>
|
</ListRows>
|
||||||
<ListSelectBanner>
|
<ListSelectBanner>
|
||||||
<template #actions="{ selections, unselectAll }">
|
<template #actions="{ selections, unselectAll }">
|
||||||
@ -167,14 +162,13 @@ import TaskStatusIcon from '@/components/Icons/TaskStatusIcon.vue'
|
|||||||
import TaskPriorityIcon from '@/components/Icons/TaskPriorityIcon.vue'
|
import TaskPriorityIcon from '@/components/Icons/TaskPriorityIcon.vue'
|
||||||
import CalendarIcon from '@/components/Icons/CalendarIcon.vue'
|
import CalendarIcon from '@/components/Icons/CalendarIcon.vue'
|
||||||
import ListBulkActions from '@/components/ListBulkActions.vue'
|
import ListBulkActions from '@/components/ListBulkActions.vue'
|
||||||
|
import ListRows from '@/components/ListViews/ListRows.vue'
|
||||||
import { formatDate } from '@/utils'
|
import { formatDate } from '@/utils'
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
ListView,
|
ListView,
|
||||||
ListHeader,
|
ListHeader,
|
||||||
ListHeaderItem,
|
ListHeaderItem,
|
||||||
ListRows,
|
|
||||||
ListRow,
|
|
||||||
ListSelectBanner,
|
ListSelectBanner,
|
||||||
ListRowItem,
|
ListRowItem,
|
||||||
ListFooter,
|
ListFooter,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user