Spaces:
Running
Running
File size: 4,970 Bytes
91677d6 c92e42a 91677d6 c92e42a 91677d6 0f00bbc 91677d6 0f00bbc 95e3d2a 91677d6 95e3d2a 8899818 95e3d2a 91677d6 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | <script lang="ts" generics="TData">
import {
type ColumnDef,
type ColumnFiltersState,
type PaginationState,
type SortingState,
type VisibilityState,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel
} from '@tanstack/table-core';
import { createSvelteTable, FlexRender } from '$lib/components/ui/data-table';
import * as Table from '$lib/components/ui/table';
import DataTableToolbar from './data-table-toolbar.svelte';
import DataTablePagination from './data-table-pagination.svelte';
import { goto } from '$app/navigation';
import { cn } from '$lib/utils';
import { untrack } from 'svelte';
interface Props {
data: TData[];
columns: ColumnDef<TData>[];
searchPlaceholder?: string;
mapOptions?: string[];
getRowHref?: (row: TData) => string;
emptyMessage?: string;
// Bindable state so the parent route can persist it across navigations
// via SvelteKit's snapshot API.
pagination?: PaginationState;
sorting?: SortingState;
columnFilters?: ColumnFiltersState;
columnVisibility?: VisibilityState;
globalFilter?: string;
}
let {
data,
columns,
searchPlaceholder,
mapOptions = [],
getRowHref,
emptyMessage = 'No results.',
pagination = $bindable<PaginationState>({ pageIndex: 0, pageSize: 25 }),
sorting = $bindable<SortingState>([]),
columnFilters = $bindable<ColumnFiltersState>([]),
columnVisibility = $bindable<VisibilityState>({}),
globalFilter = $bindable<string>('')
}: Props = $props();
// Reset to first page whenever filters change so users don't end up on an
// empty page after narrowing the result set.
$effect(() => {
void globalFilter;
void columnFilters;
untrack(() => {
if (pagination.pageIndex !== 0) {
pagination = { ...pagination, pageIndex: 0 };
}
});
});
const table = createSvelteTable<TData>({
get data() {
return data;
},
get columns() {
return columns;
},
state: {
get pagination() {
return pagination;
},
get sorting() {
return sorting;
},
get columnFilters() {
return columnFilters;
},
get columnVisibility() {
return columnVisibility;
},
get globalFilter() {
return globalFilter;
}
},
globalFilterFn: 'includesString',
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getPaginationRowModel: getPaginationRowModel(),
onPaginationChange: (u) => {
pagination = typeof u === 'function' ? u(pagination) : u;
},
onSortingChange: (u) => {
sorting = typeof u === 'function' ? u(sorting) : u;
},
onColumnFiltersChange: (u) => {
columnFilters = typeof u === 'function' ? u(columnFilters) : u;
},
onColumnVisibilityChange: (u) => {
columnVisibility = typeof u === 'function' ? u(columnVisibility) : u;
},
onGlobalFilterChange: (u) => {
globalFilter = typeof u === 'function' ? u(globalFilter) : u;
}
});
function handleRowClick(row: TData, e: MouseEvent | KeyboardEvent) {
if (!getRowHref) return;
const href = getRowHref(row);
if (e instanceof MouseEvent && (e.metaKey || e.ctrlKey || e.button === 1)) {
window.open(href, '_blank', 'noopener,noreferrer');
return;
}
goto(href);
}
</script>
<div>
<DataTableToolbar {table} {searchPlaceholder} {mapOptions} />
<div class="rounded-md border">
<Table.Root>
<Table.Header>
{#each table.getHeaderGroups() as headerGroup (headerGroup.id)}
<Table.Row class="bg-muted/40 hover:bg-muted/40">
{#each headerGroup.headers as header (header.id)}
<Table.Head class={cn('h-9 text-xs', header.column.columnDef.meta?.headClass)}>
{#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
class={cn(getRowHref && 'cursor-pointer')}
onclick={(e: MouseEvent) => handleRowClick(row.original, e)}
onkeydown={(e: KeyboardEvent) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
handleRowClick(row.original, e);
}
}}
tabindex={getRowHref ? 0 : undefined}
role={getRowHref ? 'link' : undefined}
>
{#each row.getVisibleCells() as cell (cell.id)}
<Table.Cell class={cn('py-2 align-middle', cell.column.columnDef.meta?.cellClass)}>
<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 text-sm text-muted-foreground"
>
{emptyMessage}
</Table.Cell>
</Table.Row>
{/each}
</Table.Body>
</Table.Root>
</div>
<DataTablePagination {table} />
</div>
|