Files
plantillas-proyectos/frontend/src/lib/components/dashboard/seal/data-table.svelte

113 lines
2.7 KiB
Svelte

<script lang="ts" generics="TData, TValue">
import { onMount } from 'svelte';
import type { ColumnDef } from '@tanstack/table-core';
import {
getCoreRowModel,
type TableOptions
} from '@tanstack/table-core';
import { createSvelteTable, FlexRender } from '$lib/components/ui/data-table/index.js';
import * as Table from '$lib/components/ui/table';
type Props = {
data: TData[];
columns: ColumnDef<TData, TValue>[];
loading?: boolean;
hasMore?: boolean;
loadMore?: () => void;
};
let { data, columns, loading = false, hasMore = false, loadMore }: Props = $props();
let scrollContainer: HTMLDivElement;
let observer: IntersectionObserver;
const options = $derived<TableOptions<TData>>({
get data() {
return data;
},
columns,
getCoreRowModel: getCoreRowModel()
});
const table = createSvelteTable(options);
onMount(() => {
if (!loadMore) return;
// Create intersection observer for infinite scroll
observer = new IntersectionObserver(
(entries) => {
const [entry] = entries;
if (entry.isIntersecting && hasMore && !loading && loadMore) {
loadMore();
}
},
{
root: scrollContainer,
threshold: 0.1
}
);
// Observe the last row
const lastRow = scrollContainer?.querySelector('tbody tr:last-child');
if (lastRow) {
observer.observe(lastRow);
}
return () => {
observer?.disconnect();
};
});
</script>
<div class="w-full">
<div class="rounded-md border max-h-[600px] overflow-y-auto" bind:this={scrollContainer}>
<Table.Root>
<Table.Header class="bg-background">
{#each table.getHeaderGroups() as headerGroup (headerGroup.id)}
<Table.Row>
{#each headerGroup.headers as header (header.id)}
<Table.Head>
{#if !header.isPlaceholder}
<FlexRender
content={header.column.columnDef.header}
context={header.getContext()}
/>
{/if}
</Table.Head>
{/each}
</Table.Row>
{/each}
</Table.Header>
<Table.Body>
{#each table.getRowModel().rows as row (row.id)}
<Table.Row data-state={row.getIsSelected() && "selected"}>
{#each row.getVisibleCells() as cell (cell.id)}
<Table.Cell>
<FlexRender
content={cell.column.columnDef.cell}
context={cell.getContext()}
/>
</Table.Cell>
{/each}
</Table.Row>
{:else}
<Table.Row>
<Table.Cell colspan={columns.length} class="h-24 text-center">
No hay resultados.
</Table.Cell>
</Table.Row>
{/each}
{#if loading}
<Table.Row>
<Table.Cell colspan={columns.length} class="h-12 text-center text-muted-foreground">
Cargando...
</Table.Cell>
</Table.Row>
{/if}
</Table.Body>
</Table.Root>
</div>
</div>