<script lang="ts">
import type { ColumnDef } from '@tanstack/svelte-table'
import {
FlexRender,
createTable,
tableFeatures,
} from '@tanstack/svelte-table'
import { makeData, type Person } from './makeData'
import './index.css'
let data = $state(makeData(5))
const refreshData = () => { data = makeData(5) }
const stressTest = () => { data = makeData(1_000) }
const features = tableFeatures({})
const basicColumns: ColumnDef<typeof features, Person>[] = [
{
header: 'Name',
columns: [
{
accessorKey: 'firstName',
header: 'First Name',
footer: 'First Name',
},
{
accessorFn: (row) => row.lastName,
id: 'lastName',
header: 'Last Name',
footer: 'Last Name',
},
],
},
{
header: 'Stats',
columns: [
{ accessorKey: 'age', header: 'Age', footer: 'Age' },
{ accessorKey: 'visits', header: 'Visits', footer: 'Visits' },
],
},
{
header: 'Profile',
columns: [
{ accessorKey: 'status', header: 'Status', footer: 'Status' },
{
accessorKey: 'progress',
header: 'Profile Progress',
footer: 'Profile Progress',
},
],
},
]
const nestedColumns: ColumnDef<typeof features, Person>[] = [
{
header: 'Person',
columns: [
{
header: 'Name',
columns: [
{ accessorKey: 'firstName', header: 'First Name' },
{
accessorFn: (row) => row.lastName,
id: 'lastName',
header: 'Last Name',
},
],
},
{
header: 'Demographics',
columns: [{ accessorKey: 'age', header: 'Age' }],
},
],
},
{
header: 'Activity',
columns: [
{
header: 'Engagement',
columns: [
{ accessorKey: 'visits', header: 'Visits' },
{ accessorKey: 'status', header: 'Status' },
],
},
{
header: 'Progress',
columns: [{ accessorKey: 'progress', header: 'Profile Progress' }],
},
],
},
]
const defaultColumns: ColumnDef<typeof features, Person>[] = [
{
header: 'Name',
footer: (props) => props.column.id,
columns: [
{
accessorKey: 'firstName',
cell: (info) => info.getValue(),
footer: (props) => props.column.id,
},
{
accessorFn: (row) => row.lastName,
id: 'lastName',
cell: (info) => info.getValue(),
header: () => 'Last Name',
footer: (props) => props.column.id,
},
],
},
{
header: 'Info',
footer: (props) => props.column.id,
columns: [
{
accessorKey: 'age',
header: () => 'Age',
footer: (props) => props.column.id,
},
{
header: 'More Info',
columns: [
{
accessorKey: 'visits',
header: () => 'Visits',
footer: (props) => props.column.id,
},
{
accessorKey: 'status',
header: 'Status',
footer: (props) => props.column.id,
},
{
accessorKey: 'progress',
header: 'Profile Progress',
footer: (props) => props.column.id,
},
],
},
],
},
]
const unevenColumns: ColumnDef<typeof features, Person>[] = [
{
accessorFn: (row) =>
[row.firstName, row.lastName].filter(Boolean).join(' '),
id: 'fullName',
header: 'Full Name',
cell: (info) => info.getValue(),
},
{
header: 'Info',
columns: [
{ accessorKey: 'age', header: () => 'Age' },
{
header: 'More Info',
columns: [
{ accessorKey: 'visits', header: () => 'Visits' },
{ accessorKey: 'status', header: 'Status' },
],
},
],
},
{ accessorKey: 'progress', header: 'Profile Progress' },
]
const tableOptions = (columns: ColumnDef<typeof features, Person>[]) => ({
debugTable: true,
features,
get data() {
return data
},
columns,
})
const basicTable = createTable(tableOptions(basicColumns))
const nestedTable = createTable(tableOptions(nestedColumns))
const table = createTable(tableOptions(defaultColumns))
const unevenTable = createTable(tableOptions(unevenColumns))
</script>
<div class="demo-root">
<div>
<button onclick={() => refreshData()}>Regenerate Data</button>
<button onclick={() => stressTest()}>Stress Test (1k rows)</button>
</div>
<div class="spacer-md"></div>
<div class="example-grid">
<section class="example-panel">
<h2 class="section-title">Basic Header Groups</h2>
<table>
<thead>
{#each basicTable.getHeaderGroups() as headerGroup (headerGroup.id)}
<tr>
{#each headerGroup.headers as header (header.id)}
<th colSpan={header.colSpan}>
<FlexRender header={header} />
</th>
{/each}
</tr>
{/each}
</thead>
<tbody>
{#each basicTable.getRowModel().rows as row (row.id)}
<tr>
{#each row.getAllCells() as cell (cell.id)}
<td>
<FlexRender cell={cell} />
</td>
{/each}
</tr>
{/each}
</tbody>
<tfoot>
{#each basicTable
.getFooterGroups()
.filter((footerGroup) => footerGroup.headers.some((header) => !header.isPlaceholder && header.column.columnDef.footer)) as footerGroup (footerGroup.id)}
<tr>
{#each footerGroup.headers as header (header.id)}
<th colSpan={header.colSpan}>
{#if !header.isPlaceholder}
<FlexRender footer={header} />
{/if}
</th>
{/each}
</tr>
{/each}
</tfoot>
</table>
</section>
<section class="example-panel">
<h2 class="section-title">Nested Header Groups</h2>
<table>
<thead>
{#each nestedTable.getHeaderGroups() as headerGroup (headerGroup.id)}
<tr>
{#each headerGroup.headers as header (header.id)}
<th colSpan={header.colSpan}>
<FlexRender header={header} />
</th>
{/each}
</tr>
{/each}
</thead>
<tbody>
{#each nestedTable.getRowModel().rows as row (row.id)}
<tr>
{#each row.getAllCells() as cell (cell.id)}
<td>
<FlexRender cell={cell} />
</td>
{/each}
</tr>
{/each}
</tbody>
</table>
</section>
<section class="example-panel">
<h2 class="section-title">Placeholder Headers</h2>
<table>
<thead>
{#each table.getHeaderGroups() as headerGroup (headerGroup.id)}
<tr>
{#each headerGroup.headers as header (header.id)}
<th colSpan={header.colSpan}>
{#if !header.isPlaceholder}
<FlexRender header={header} />
{/if}
</th>
{/each}
</tr>
{/each}
</thead>
<tbody>
{#each table.getRowModel().rows as row (row.id)}
<tr>
{#each row.getAllCells() as cell (cell.id)}
<td>
<FlexRender cell={cell} />
</td>
{/each}
</tr>
{/each}
</tbody>
<tfoot>
{#each table.getFooterGroups() as footerGroup (footerGroup.id)}
<tr>
{#each footerGroup.headers as header (header.id)}
<th colSpan={header.colSpan}>
{#if !header.isPlaceholder}
<FlexRender footer={header} />
{/if}
</th>
{/each}
</tr>
{/each}
</tfoot>
</table>
</section>
<section class="example-panel">
<h2 class="section-title">Header Row Spanning</h2>
<table>
<thead>
{#each unevenTable.getHeaderGroups() as headerGroup (headerGroup.id)}
<tr>
{#each headerGroup.headers as header (header.id)}
{#if header.rowSpan !== 0}
<th colSpan={header.colSpan} rowSpan={header.rowSpan}>
<FlexRender header={header} />
</th>
{/if}
{/each}
</tr>
{/each}
</thead>
<tbody>
{#each unevenTable.getRowModel().rows as row (row.id)}
<tr>
{#each row.getAllCells() as cell (cell.id)}
<td>
<FlexRender cell={cell} />
</td>
{/each}
</tr>
{/each}
</tbody>
</table>
</section>
</div>
</div>