mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-18 06:13:52 +02:00
refactor: remove useDataTableScrollHeight and introducing an auto-height prop and CSS class.
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div class="flex flex-col min-w-0 data-table">
|
||||
<div :class="['flex flex-col min-w-0 data-table', autoHeight && 'flex-1 min-h-0 overflow-hidden']">
|
||||
<div v-if="$slots.toolbar" class="mb-2">
|
||||
<slot name="toolbar"></slot>
|
||||
</div>
|
||||
|
||||
<div class="rounded-md border">
|
||||
<div ref="tableScrollRef" class="max-w-full overflow-auto relative" :style="tableStyle">
|
||||
<div :class="['rounded-md border', autoHeight && 'flex-1 min-h-0 flex flex-col overflow-hidden']">
|
||||
<div ref="tableScrollRef" :class="['max-w-full overflow-auto relative', autoHeight && 'flex-1 min-h-0']" :style="tableStyle">
|
||||
<Table :class="tableClassValue" :style="tableElementStyle">
|
||||
<colgroup>
|
||||
<col v-for="col in table.getVisibleLeafColumns()" :key="col.id" :style="getColStyle(col)" />
|
||||
@@ -259,7 +259,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="showPagination" class="mt-4 flex w-full items-center gap-3">
|
||||
<div v-if="showPagination" class="mt-4 flex w-full items-center gap-3 mb-1">
|
||||
<div v-if="pageSizes.length" class="inline-flex items-center flex-1 justify-end gap-2">
|
||||
<span class="text-xs text-muted-foreground truncate">{{ t('table.pagination.rows_per_page') }}</span>
|
||||
<Select v-model="pageSizeValue">
|
||||
@@ -399,6 +399,10 @@
|
||||
enableColumnVisibility: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
autoHeight: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
|
||||
|
||||
export function useDataTableScrollHeight(containerRef, options = {}) {
|
||||
const {
|
||||
offset = 127,
|
||||
toolbarHeight = 0,
|
||||
paginationHeight = 0,
|
||||
extraOffsetRefs = [],
|
||||
subtractContainerPadding = false
|
||||
} = options;
|
||||
|
||||
const maxHeight = ref(0);
|
||||
|
||||
let resizeObserver;
|
||||
const observedElements = new Set();
|
||||
|
||||
const getPadding = (el) => {
|
||||
if (!subtractContainerPadding || !el) {
|
||||
return 0;
|
||||
}
|
||||
const style = getComputedStyle(el);
|
||||
return (
|
||||
(Number.parseFloat(style.paddingTop) || 0) +
|
||||
(Number.parseFloat(style.paddingBottom) || 0)
|
||||
);
|
||||
};
|
||||
|
||||
const getHeight = (maybeRef) => {
|
||||
const el = maybeRef?.value;
|
||||
return el && typeof el.getBoundingClientRect === 'function'
|
||||
? el.getBoundingClientRect().height
|
||||
: 0;
|
||||
};
|
||||
|
||||
const recalc = () => {
|
||||
const containerEl = containerRef?.value;
|
||||
if (!containerEl) {
|
||||
return;
|
||||
}
|
||||
|
||||
const extraOffset = extraOffsetRefs.reduce(
|
||||
(sum, ref) => sum + getHeight(ref),
|
||||
0
|
||||
);
|
||||
|
||||
const available =
|
||||
containerEl.clientHeight -
|
||||
getPadding(containerEl) -
|
||||
offset -
|
||||
toolbarHeight -
|
||||
paginationHeight -
|
||||
extraOffset;
|
||||
|
||||
maxHeight.value = Math.max(0, available);
|
||||
};
|
||||
|
||||
const updateObservedElements = () => {
|
||||
if (!resizeObserver) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextObserved = new Set(
|
||||
[
|
||||
containerRef?.value,
|
||||
...extraOffsetRefs.map((ref) => ref?.value)
|
||||
].filter(Boolean)
|
||||
);
|
||||
|
||||
for (const el of observedElements) {
|
||||
if (!nextObserved.has(el)) {
|
||||
resizeObserver.unobserve(el);
|
||||
observedElements.delete(el);
|
||||
}
|
||||
}
|
||||
|
||||
for (const el of nextObserved) {
|
||||
if (!observedElements.has(el)) {
|
||||
resizeObserver.observe(el);
|
||||
observedElements.add(el);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
resizeObserver = new ResizeObserver(recalc);
|
||||
|
||||
updateObservedElements();
|
||||
recalc();
|
||||
});
|
||||
|
||||
watch(
|
||||
() => [containerRef?.value, ...extraOffsetRefs.map((r) => r?.value)],
|
||||
() => {
|
||||
updateObservedElements();
|
||||
recalc();
|
||||
},
|
||||
{ flush: 'post' }
|
||||
);
|
||||
|
||||
onUnmounted(() => {
|
||||
resizeObserver?.disconnect();
|
||||
observedElements.clear();
|
||||
});
|
||||
|
||||
const tableStyle = computed(() => {
|
||||
if (!Number.isFinite(maxHeight.value) || maxHeight.value <= 0)
|
||||
return undefined;
|
||||
return { maxHeight: `${maxHeight.value}px` };
|
||||
});
|
||||
|
||||
return {
|
||||
tableStyle
|
||||
};
|
||||
}
|
||||
@@ -197,6 +197,12 @@ html {
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.x-container--auto-height {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.aside-collapsed .x-container {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="x-container feed" ref="feedRef">
|
||||
<div class="x-container feed x-container--auto-height" ref="feedRef">
|
||||
<DataTableLayout
|
||||
:table="table"
|
||||
:loading="feedTable.loading"
|
||||
:table-style="tableHeightStyle"
|
||||
auto-height
|
||||
:page-sizes="pageSizes"
|
||||
:total-items="totalItems"
|
||||
:on-page-size-change="handlePageSizeChange">
|
||||
@@ -86,7 +86,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
import { ListFilter, Star } from 'lucide-vue-next';
|
||||
import { getLocalTimeZone, today } from '@internationalized/date';
|
||||
import { storeToRefs } from 'pinia';
|
||||
@@ -104,7 +104,6 @@
|
||||
import { RangeCalendar } from '../../components/ui/range-calendar';
|
||||
import { Toggle } from '../../components/ui/toggle';
|
||||
import { columns as baseColumns } from './columns.jsx';
|
||||
import { useDataTableScrollHeight } from '../../composables/useDataTableScrollHeight';
|
||||
import { useVrcxVueTable } from '../../lib/table/useVrcxVueTable';
|
||||
|
||||
const { feedTable, feedTableData } = storeToRefs(useFeedStore());
|
||||
@@ -154,13 +153,6 @@
|
||||
|
||||
const feedRef = ref(null);
|
||||
|
||||
// TODO: simplify
|
||||
const { tableStyle: tableHeightStyle } = useDataTableScrollHeight(feedRef, {
|
||||
offset: 30,
|
||||
toolbarHeight: 54,
|
||||
paginationHeight: 52
|
||||
});
|
||||
|
||||
const pageSizes = computed(() => appearanceSettingsStore.tablePageSizes);
|
||||
|
||||
/**
|
||||
|
||||
@@ -67,12 +67,6 @@ vi.mock('../../../lib/table/useVrcxVueTable', () => ({
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('../../../composables/useDataTableScrollHeight', () => ({
|
||||
useDataTableScrollHeight: () => ({
|
||||
tableStyle: {}
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('../columns.jsx', () => ({
|
||||
columns: []
|
||||
}));
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div class="x-container" ref="friendsListRef">
|
||||
<div>
|
||||
<div class="x-container x-container--auto-height" ref="friendsListRef">
|
||||
<div class="flex-1 min-h-0 flex flex-col">
|
||||
<DataTableLayout
|
||||
class="min-w-0 w-full"
|
||||
:table="table"
|
||||
:loading="friendsListLoading"
|
||||
:table-style="tableHeightStyle"
|
||||
auto-height
|
||||
:page-sizes="pageSizes"
|
||||
:total-items="totalItems"
|
||||
table-class="min-w-max w-max [&_tbody_tr]:cursor-pointer"
|
||||
@@ -144,7 +144,6 @@
|
||||
import { localeIncludes } from '../../shared/utils';
|
||||
import removeConfusables, { removeWhitespace } from '../../services/confusables';
|
||||
import { router } from '../../plugins/router';
|
||||
import { useDataTableScrollHeight } from '../../composables/useDataTableScrollHeight';
|
||||
import { useVrcxVueTable } from '../../lib/table/useVrcxVueTable';
|
||||
import { showUserDialog } from '../../coordinators/userCoordinator';
|
||||
import { confirmDeleteFriend, handleFriendDelete } from '../../coordinators/friendRelationshipCoordinator';
|
||||
@@ -184,11 +183,6 @@
|
||||
});
|
||||
|
||||
const friendsListRef = ref(null);
|
||||
const { tableStyle: tableHeightStyle } = useDataTableScrollHeight(friendsListRef, {
|
||||
offset: 30,
|
||||
toolbarHeight: 54,
|
||||
paginationHeight: 52
|
||||
});
|
||||
|
||||
const friendsListColumns = computed(() =>
|
||||
createColumns({
|
||||
|
||||
@@ -127,12 +127,6 @@ vi.mock('../../../shared/utils', () => ({
|
||||
.includes(String(query ?? '').toLowerCase())
|
||||
}));
|
||||
|
||||
vi.mock('../../../composables/useDataTableScrollHeight', () => ({
|
||||
useDataTableScrollHeight: () => ({
|
||||
tableStyle: {}
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('../../../lib/table/useVrcxVueTable', () => ({
|
||||
useVrcxVueTable: (options) => ({
|
||||
table: {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="x-container" ref="friendLogRef">
|
||||
<div class="x-container x-container--auto-height" ref="friendLogRef">
|
||||
<DataTableLayout
|
||||
:table="table"
|
||||
:loading="friendLogTable.loading"
|
||||
:table-style="tableHeightStyle"
|
||||
auto-height
|
||||
:page-sizes="pageSizes"
|
||||
:total-items="totalItems"
|
||||
:on-page-size-change="handlePageSizeChange">
|
||||
@@ -61,7 +61,6 @@
|
||||
import { createColumns } from './columns.jsx';
|
||||
import { database } from '../../services/database';
|
||||
import { removeFromArray } from '../../shared/utils';
|
||||
import { useDataTableScrollHeight } from '../../composables/useDataTableScrollHeight';
|
||||
import { useVrcxVueTable } from '../../lib/table/useVrcxVueTable';
|
||||
|
||||
import configRepository from '../../services/config';
|
||||
@@ -73,11 +72,6 @@
|
||||
const { friendLogTable } = storeToRefs(useFriendStore());
|
||||
|
||||
const friendLogRef = ref(null);
|
||||
const { tableStyle: tableHeightStyle } = useDataTableScrollHeight(friendLogRef, {
|
||||
offset: 30,
|
||||
toolbarHeight: 54,
|
||||
paginationHeight: 52
|
||||
});
|
||||
|
||||
const friendLogDisplayData = computed(() => {
|
||||
const data = friendLogTable.value.data;
|
||||
|
||||
@@ -55,12 +55,6 @@ vi.mock('../../../stores', () => ({
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('../../../composables/useDataTableScrollHeight', () => ({
|
||||
useDataTableScrollHeight: () => ({
|
||||
tableStyle: {}
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('../../../lib/table/useVrcxVueTable', () => ({
|
||||
useVrcxVueTable: (options) => ({
|
||||
table: {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="x-container" ref="gameLogRef">
|
||||
<div class="x-container x-container--auto-height" ref="gameLogRef">
|
||||
<DataTableLayout
|
||||
:table="table"
|
||||
:loading="gameLogTable.loading"
|
||||
:table-style="tableHeightStyle"
|
||||
auto-height
|
||||
:page-sizes="pageSizes"
|
||||
:total-items="totalItems"
|
||||
:on-page-size-change="handlePageSizeChange">
|
||||
@@ -82,7 +82,6 @@
|
||||
import { createColumns } from './columns.jsx';
|
||||
import { database } from '../../services/database';
|
||||
import { removeFromArray } from '../../shared/utils';
|
||||
import { useDataTableScrollHeight } from '../../composables/useDataTableScrollHeight';
|
||||
import { useVrcxVueTable } from '../../lib/table/useVrcxVueTable';
|
||||
|
||||
const { gameLogTableLookup } = useGameLogStore();
|
||||
@@ -111,11 +110,6 @@
|
||||
const { t } = useI18n();
|
||||
|
||||
const gameLogRef = ref(null);
|
||||
const { tableStyle: tableHeightStyle } = useDataTableScrollHeight(gameLogRef, {
|
||||
offset: 30,
|
||||
toolbarHeight: 54,
|
||||
paginationHeight: 52
|
||||
});
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -48,9 +48,6 @@ vi.mock('../../../services/database', () => ({
|
||||
database: { deleteGameLogEntry: vi.fn() }
|
||||
}));
|
||||
vi.mock('../../../shared/utils', () => ({ removeFromArray: vi.fn() }));
|
||||
vi.mock('../../../composables/useDataTableScrollHeight', () => ({
|
||||
useDataTableScrollHeight: () => ({ tableStyle: ref({}) })
|
||||
}));
|
||||
vi.mock('../../../lib/table/useVrcxVueTable', () => ({
|
||||
useVrcxVueTable: () => ({
|
||||
table: { getFilteredRowModel: () => ({ rows: [] }) },
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="x-container" ref="moderationRef">
|
||||
<div class="x-container x-container--auto-height" ref="moderationRef">
|
||||
<div class="mb-4 flex items-center">
|
||||
<Select
|
||||
multiple
|
||||
@@ -40,7 +40,7 @@
|
||||
<DataTableLayout
|
||||
:table="table"
|
||||
:loading="playerModerationTable.loading"
|
||||
:table-style="tableHeightStyle"
|
||||
auto-height
|
||||
:page-sizes="pageSizes"
|
||||
:total-items="totalItems"
|
||||
:on-page-size-change="handlePageSizeChange" />
|
||||
@@ -63,7 +63,6 @@
|
||||
import { createColumns } from './columns.jsx';
|
||||
import { moderationTypes } from '../../shared/constants';
|
||||
import { playerModerationRequest } from '../../api';
|
||||
import { useDataTableScrollHeight } from '../../composables/useDataTableScrollHeight';
|
||||
import { useVrcxVueTable } from '../../lib/table/useVrcxVueTable';
|
||||
|
||||
import configRepository from '../../services/config.js';
|
||||
@@ -76,11 +75,6 @@
|
||||
const modalStore = useModalStore();
|
||||
|
||||
const moderationRef = ref(null);
|
||||
const { tableStyle: tableHeightStyle } = useDataTableScrollHeight(moderationRef, {
|
||||
offset: 30,
|
||||
toolbarHeight: 54,
|
||||
paginationHeight: 52
|
||||
});
|
||||
|
||||
async function init() {
|
||||
playerModerationTable.value.filters[0].value = JSON.parse(
|
||||
|
||||
@@ -103,12 +103,6 @@ vi.mock('../../../lib/table/useVrcxVueTable', () => ({
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('../../../composables/useDataTableScrollHeight', () => ({
|
||||
useDataTableScrollHeight: () => ({
|
||||
tableStyle: {}
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('@/components/ui/select', () => ({
|
||||
Select: {
|
||||
template: '<div><slot /></div>'
|
||||
|
||||
@@ -167,7 +167,7 @@
|
||||
<DataTableLayout
|
||||
v-if="viewMode === 'table'"
|
||||
:table="table"
|
||||
:table-style="tableHeightStyle"
|
||||
auto-height
|
||||
:page-sizes="pageSizes"
|
||||
:total-items="filteredAvatars.length"
|
||||
:loading="isLoading"
|
||||
@@ -340,7 +340,6 @@
|
||||
import { getTagColor } from '../../shared/constants';
|
||||
import { processBulk } from '../../services/request';
|
||||
import { useAvatarCardGrid } from './composables/useAvatarCardGrid';
|
||||
import { useDataTableScrollHeight } from '../../composables/useDataTableScrollHeight';
|
||||
import { useVrcxVueTable } from '../../lib/table/useVrcxVueTable';
|
||||
|
||||
import ImageCropDialog from '../../components/dialogs/ImageCropDialog.vue';
|
||||
@@ -375,11 +374,7 @@
|
||||
const manageTagsOpen = ref(false);
|
||||
const manageTagsAvatar = ref(null);
|
||||
|
||||
const { tableStyle: tableHeightStyle } = useDataTableScrollHeight(containerRef, {
|
||||
offset: 30,
|
||||
toolbarHeight: 54,
|
||||
paginationHeight: 52
|
||||
});
|
||||
|
||||
|
||||
const allTags = computed(() => {
|
||||
const tagSet = new Set();
|
||||
|
||||
@@ -154,12 +154,6 @@ vi.mock('../composables/useAvatarCardGrid.js', () => ({
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('../../../composables/useDataTableScrollHeight', () => ({
|
||||
useDataTableScrollHeight: () => ({
|
||||
tableStyle: {}
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('../../../lib/table/useVrcxVueTable', () => ({
|
||||
useVrcxVueTable: () => ({
|
||||
table: {},
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="x-container" ref="notificationsRef">
|
||||
<div class="x-container x-container--auto-height" ref="notificationsRef">
|
||||
<DataTableLayout
|
||||
:table="table"
|
||||
:loading="isNotificationsLoading"
|
||||
:table-style="tableHeightStyle"
|
||||
auto-height
|
||||
:page-sizes="pageSizes"
|
||||
:total-items="totalItems"
|
||||
:on-page-size-change="handlePageSizeChange">
|
||||
@@ -104,7 +104,6 @@
|
||||
import { DataTableLayout } from '../../components/ui/data-table';
|
||||
import { convertFileUrlToImageUrl } from '../../shared/utils';
|
||||
import { createColumns } from './columns.jsx';
|
||||
import { useDataTableScrollHeight } from '../../composables/useDataTableScrollHeight';
|
||||
import { useVrcxVueTable } from '../../lib/table/useVrcxVueTable';
|
||||
|
||||
import SendInviteRequestResponseDialog from './dialogs/SendInviteRequestResponseDialog.vue';
|
||||
@@ -132,11 +131,6 @@
|
||||
const { t } = useI18n();
|
||||
|
||||
const notificationsRef = ref(null);
|
||||
const { tableStyle: tableHeightStyle } = useDataTableScrollHeight(notificationsRef, {
|
||||
offset: 30,
|
||||
toolbarHeight: 54,
|
||||
paginationHeight: 52
|
||||
});
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="x-container" ref="playerListRef">
|
||||
<div class="x-container x-container--auto-height" ref="playerListRef">
|
||||
<div class="flex h-full min-h-0 flex-col overflow-y-auto overflow-x-hidden">
|
||||
<div
|
||||
v-if="currentInstanceWorld.ref.id"
|
||||
@@ -168,7 +168,7 @@
|
||||
<DataTableLayout
|
||||
class="[&_th]:px-2.5! [&_th]:py-0.75! [&_td]:px-2.5! [&_td]:py-0.75! [&_tr]:h-7!"
|
||||
:table="playerListTable"
|
||||
:table-style="playerListTableStyle"
|
||||
auto-height
|
||||
:loading="false"
|
||||
:show-pagination="false"
|
||||
:on-row-click="handlePlayerListRowClick" />
|
||||
@@ -198,7 +198,6 @@
|
||||
import { Badge } from '../../components/ui/badge';
|
||||
import { DataTableLayout } from '../../components/ui/data-table';
|
||||
import { createColumns } from './columns.jsx';
|
||||
import { useDataTableScrollHeight } from '../../composables/useDataTableScrollHeight';
|
||||
import { useVrcxVueTable } from '../../lib/table/useVrcxVueTable';
|
||||
|
||||
import ChatboxBlacklistDialog from './dialogs/ChatboxBlacklistDialog.vue';
|
||||
@@ -231,12 +230,6 @@
|
||||
const playerListRef = ref(null);
|
||||
const playerListHeaderRef = ref(null);
|
||||
const playerListPhotonRef = ref(null);
|
||||
const { tableStyle: playerListTableStyle } = useDataTableScrollHeight(playerListRef, {
|
||||
offset: 30,
|
||||
paginationHeight: 0,
|
||||
subtractContainerPadding: true,
|
||||
extraOffsetRefs: [playerListHeaderRef, playerListPhotonRef]
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
|
||||
@@ -108,12 +108,6 @@ vi.mock('../../../lib/table/useVrcxVueTable', () => ({
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('../../../composables/useDataTableScrollHeight', () => ({
|
||||
useDataTableScrollHeight: () => ({
|
||||
tableStyle: {}
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('../columns.jsx', () => ({
|
||||
createColumns: () => [{ id: 'photonId' }]
|
||||
}));
|
||||
|
||||
Reference in New Issue
Block a user