Reworked the table scroll
This commit is contained in:
@@ -11,8 +11,11 @@ import {
|
||||
PointElement,
|
||||
LineElement,
|
||||
} from 'chart.js';
|
||||
import { computed, ref } from 'vue';
|
||||
import { ArrowDown, ArrowUp } from 'lucide-vue-next';
|
||||
import { computed, nextTick, ref, watch } from 'vue';
|
||||
import LinkHeader from '@/components/LinkHeader.vue';
|
||||
import Button from '@/components/ui/button/Button.vue';
|
||||
import ScrollArea from '@/components/ui/scroll-area/ScrollArea.vue';
|
||||
import { usePerceptronTraining } from '@/composables/usePerceptronTraining';
|
||||
import type { Dataset, DatasetPoint, InitializationMethod, PerceptronType } from '@/types/perceptron';
|
||||
import IterationTable from '../components/IterationTable.vue';
|
||||
@@ -105,11 +108,22 @@ function getActivationFunction(type: string): (x: number) => number {
|
||||
}
|
||||
}
|
||||
|
||||
const iterationScrollArea = ref<{
|
||||
followBottom: (force?: boolean) => void;
|
||||
isFollowingBottom: boolean;
|
||||
scrollToTop: (behavior?: ScrollBehavior) => void;
|
||||
} | null>(null);
|
||||
|
||||
watch([iterations, trainingEnded], async () => {
|
||||
await nextTick();
|
||||
iterationScrollArea.value?.followBottom();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head title="Perceptron Viewer"></Head>
|
||||
<main class="space-y-6">
|
||||
<main class="flex min-h-dvh flex-col gap-6 pb-6 space-y-6">
|
||||
<LinkHeader class="w-full" />
|
||||
<PerceptronSetup
|
||||
:type="props.type"
|
||||
@@ -130,18 +144,56 @@ function getActivationFunction(type: string): (x: number) => number {
|
||||
@update:training-id="setTrainingId"
|
||||
/>
|
||||
<div
|
||||
class="align-items-start justify-content-center flex h-full min-h-dvh max-w-dvw"
|
||||
class="align-items-start justify-content-center grid max-w-dvw grid-cols-2"
|
||||
v-if="selectedDatasetName || iterations.length > 0"
|
||||
>
|
||||
<div class="max-h-full w-full overflow-y-scroll">
|
||||
<IterationTable
|
||||
:iterations="iterations"
|
||||
:trainingEnded="trainingEnded"
|
||||
:trainingEndReason="trainingEndReason"
|
||||
:maxDisplayedWeights="props.maxDisplayedWeights"
|
||||
/>
|
||||
<div class="pt-3 h-dvh max-h-dvh min-h-0 w-full min-w-0">
|
||||
<ScrollArea ref="iterationScrollArea" :keep-bottom="true" type="scroll" class="relative h-full max-h-full min-h-0 w-full">
|
||||
<IterationTable
|
||||
:iterations="iterations"
|
||||
:trainingEnded="trainingEnded"
|
||||
:trainingEndReason="trainingEndReason"
|
||||
:maxDisplayedWeights="props.maxDisplayedWeights"
|
||||
/>
|
||||
<template #overlay>
|
||||
<div class="absolute right-4 bottom-4 z-10 flex flex-col items-end gap-2">
|
||||
<Button
|
||||
type="button"
|
||||
variant="secondary"
|
||||
size="icon"
|
||||
class="size-9 rounded-full shadow-md"
|
||||
aria-label="Revenir en haut du tableau"
|
||||
title="Revenir en haut"
|
||||
@click="iterationScrollArea?.scrollToTop()"
|
||||
>
|
||||
<ArrowUp class="size-4" />
|
||||
</Button>
|
||||
<Transition
|
||||
enter-active-class="transition-opacity duration-300 ease-in-out"
|
||||
enter-from-class="opacity-0"
|
||||
enter-to-class="opacity-100"
|
||||
leave-active-class="transition-opacity duration-300 ease-in-out"
|
||||
leave-from-class="opacity-100"
|
||||
leave-to-class="opacity-0"
|
||||
>
|
||||
<Button
|
||||
v-if="iterationScrollArea && !iterationScrollArea.isFollowingBottom"
|
||||
type="button"
|
||||
variant="secondary"
|
||||
size="icon"
|
||||
class="size-9 rounded-full shadow-md"
|
||||
aria-label="Reprendre le défilement automatique"
|
||||
title="Reprendre le défilement automatique"
|
||||
@click="iterationScrollArea?.followBottom(true)"
|
||||
>
|
||||
<ArrowDown class="size-4" />
|
||||
</Button>
|
||||
</Transition>
|
||||
</div>
|
||||
</template>
|
||||
</ScrollArea>
|
||||
</div>
|
||||
<div class="sticky top-0 h-full w-full">
|
||||
<div class="h-full w-full min-w-0 space-y-6">
|
||||
<div>
|
||||
<PerceptronDecisionGraph
|
||||
:cleanedDataset="cleanedDataset"
|
||||
@@ -163,3 +215,16 @@ function getActivationFunction(type: string): (x: number) => number {
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<style lang="css" scoped>
|
||||
/* we will explain what these classes do next! */
|
||||
.v-enter-active,
|
||||
.v-leave-active {
|
||||
transition: opacity 0.5s ease;
|
||||
}
|
||||
|
||||
.v-enter-from,
|
||||
.v-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user