wip: rewrite playerlist

This commit is contained in:
pa
2026-01-07 16:20:52 +09:00
committed by Natsumi
parent 9ae8789d14
commit 6cfefb50ab
6 changed files with 641 additions and 346 deletions

View File

@@ -1,13 +1,31 @@
import { computed, onMounted, onUnmounted, ref } from 'vue';
import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
export function useDataTableScrollHeight(containerRef, options = {}) {
const offset = options.offset ?? 127;
const toolbarHeight = options.toolbarHeight ?? 0;
const paginationHeight = options.paginationHeight ?? 0;
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;
@@ -15,38 +33,68 @@ export function useDataTableScrollHeight(containerRef, options = {}) {
return;
}
const extraOffset = extraOffsetRefs.reduce((sum, ref) => sum + getHeight(ref), 0);
const available =
containerEl.clientHeight -
getPadding(containerEl) -
offset -
toolbarHeight -
paginationHeight;
paginationHeight -
extraOffset;
maxHeight.value = Math.max(0, available);
};
onMounted(() => {
recalc();
resizeObserver = new ResizeObserver(() => {
recalc();
});
if (containerRef?.value) {
resizeObserver.observe(containerRef.value);
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`
};
if (!Number.isFinite(maxHeight.value) || maxHeight.value <= 0) return undefined;
return { maxHeight: `${maxHeight.value}px` };
});
return {