6ee4087a29
- 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.
57 lines
1.7 KiB
Vue
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> |