Files
veridian/app/components/RowVirtualizerDynamic.vue
T
zoeissleeping 6ee4087a29 ♻️ refactor: optimize state management, switch to @tanstack/vue-virtual, and improve performance
- Centralize `useAgents` and `useModels` state within the Nuxt app context to prevent data leaks and improve initialization.
- Migrate virtualization from `vue-virtual-scroller` to `@tanstack/vue-virtual` with new `RowVirtualizerFixed` and `RowVirtualizerDynamic` components.
- Upgrade Nuxt to v4.3.1 and remove `@vue-macros/nuxt`.
- Replace `big.js` with an optimized custom `lshDecimal` string manipulation logic for pricing calculations in the provider API.
- Implement automatic focus redirection in `ChatInput` to capture standard keyboard input.
- Refactor Sidenav and Settings components to utilize virtualization for long lists (topics, agents, models).
- Enhance theme colors and mobile experience. More work to come on both of these.
2026-02-23 15:56:10 +00:00

57 lines
1.7 KiB
Vue

<script setup lang="ts">
import { useVirtualizer } from '@tanstack/vue-virtual';
const props = defineProps<{
items: any[];
keyField?: string;
scrollElement: HTMLElement | null;
minItemSize: number;
overscan: number;
prerender?: number;
}>();
const rowVirtualizer = useVirtualizer(computed(() => ({
count: props.items.length,
getScrollElement: () => props.scrollElement,
estimateSize: () => props.minItemSize,
overscan: props.overscan,
getItemKey: (index: number) => props.keyField ? props.items[index]?.[props.keyField] || index : index,
initialRect: {
width: 0,
height: props.prerender ? props.minItemSize * props.prerender : 0
},
})));
const virtualRows = computed(() => rowVirtualizer.value.getVirtualItems());
const totalSize = computed(() => rowVirtualizer.value.getTotalSize());
const measureElement = (el: Element) => {
if (!el) {
return
}
rowVirtualizer.value.measureElement(el)
return undefined
}
watch(() => props.items, () => {
rowVirtualizer.value.measure();
}, { deep: false });
</script>
<template>
<div :style="{ height: `${totalSize}px`, width: '100%', position: 'relative' }">
<div v-for="virtualRow in virtualRows" :ref="(el) => measureElement(el as Element)"
:key="(virtualRow.key as any | number)" :data-index="virtualRow.index" :style="{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: `${virtualRow.size}`,
transform: `translateY(${virtualRow.start}px)`,
}">
<slot :item="props.items[virtualRow.index]" :index="virtualRow.index" />
</div>
</div>
</template>