Skip to content

Commit d1ce4bd

Browse files
committed
feat: enhance table with pagination and column visibility
- Add pagination with flexible page size controls - Add column visibility toggling - Implement row identification with ID tracking - Add logging system for errors and warnings - Create example components demonstrating features
1 parent 746212c commit d1ce4bd

File tree

12 files changed

+856
-52
lines changed

12 files changed

+856
-52
lines changed

.changeset/olive-animals-hope.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
'svelte-reactive-table': minor
3+
---
4+
5+
feat: enhance table with pagination and column visibility
6+
7+
- Add pagination with flexible page size controls
8+
- Add column visibility toggling
9+
- Implement row identification with ID tracking
10+
- Add logging system for errors and warnings
11+
- Create example components demonstrating features

packages/svelte-reactive-table/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414
"lint": "prettier --config ../../.prettierrc --check .",
1515
"test:unit": "vitest",
1616
"test": "npm run test:unit -- --run",
17-
"size": "size-limit",
18-
"analyze": "size-limit --why"
17+
"size": "pnpm build && size-limit"
1918
},
2019
"files": [
2120
"dist",
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<script lang="ts">
2+
import { reactiveTable } from '$lib/index.js';
3+
import { initialData } from './data.js';
4+
5+
// Basic table example
6+
const basicTable = reactiveTable(initialData, [
7+
{ accessor: 'id', header: 'ID', isIdentifier: true },
8+
{ accessor: 'name', header: 'Name' },
9+
{ accessor: 'age', header: 'Age' },
10+
{ accessor: 'city', header: 'City' }
11+
]);
12+
13+
function addNewRow() {
14+
basicTable.data.push({
15+
name: 'New Hero',
16+
age: Math.floor(Math.random() * 100),
17+
city: 'New City',
18+
id: Math.floor(Math.random() * 1000)
19+
});
20+
}
21+
</script>
22+
23+
<section class="max-w-5xl mx-auto my-8 px-4">
24+
<h2 class="text-2xl font-bold mb-6 text-gray-800 border-b pb-2">Data Table</h2>
25+
26+
<div class="bg-white rounded-lg shadow-md overflow-hidden border border-gray-200">
27+
<div class="overflow-x-auto">
28+
<table class="w-full">
29+
<thead>
30+
<tr class="bg-gray-50 border-b border-gray-200">
31+
{#each basicTable.headers as header}
32+
<th
33+
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
34+
>{header}</th
35+
>
36+
{/each}
37+
</tr>
38+
</thead>
39+
<tbody class="divide-y divide-gray-200">
40+
{#each basicTable.allRows as row, i}
41+
<tr class="hover:bg-gray-50 transition-colors duration-150 ease-in-out">
42+
{#each row.cells as cell}
43+
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{cell.value}</td>
44+
{/each}
45+
</tr>
46+
{/each}
47+
{#if basicTable.allRows.length === 0}
48+
<tr>
49+
<td
50+
colspan={basicTable.headers.length}
51+
class="px-6 py-8 text-center text-sm text-gray-500"
52+
>
53+
No data available
54+
</td>
55+
</tr>
56+
{/if}
57+
</tbody>
58+
</table>
59+
</div>
60+
</div>
61+
62+
<div class="mt-6 flex justify-end">
63+
<button
64+
class="flex items-center gap-2 px-4 py-2 bg-emerald-600 hover:bg-emerald-700 text-white font-medium rounded-md shadow-sm transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-emerald-500 focus:ring-offset-2"
65+
onclick={() => addNewRow()}
66+
>
67+
<svg
68+
xmlns="http://www.w3.org/2000/svg"
69+
class="h-5 w-5"
70+
viewBox="0 0 20 20"
71+
fill="currentColor"
72+
>
73+
<path
74+
fill-rule="evenodd"
75+
d="M10 5a1 1 0 011 1v3h3a1 1 0 110 2h-3v3a1 1 0 11-2 0v-3H6a1 1 0 110-2h3V6a1 1 0 011-1z"
76+
clip-rule="evenodd"
77+
/>
78+
</svg>
79+
Add New Row
80+
</button>
81+
</div>
82+
</section>
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<script lang="ts">
2+
import { reactiveTable } from '$lib/index.js';
3+
import { initialData, type Person } from './data.js';
4+
5+
// Toggle column visibility example
6+
const visibilityTable = reactiveTable(initialData, [
7+
{ accessor: 'id', header: 'ID', isIdentifier: true },
8+
{ accessor: 'name', header: 'Name' },
9+
{ accessor: 'age', header: 'Age' },
10+
{ accessor: 'city', header: 'City' }
11+
]);
12+
13+
function toggleColumn(accessor: keyof Person) {
14+
visibilityTable.toggleColumnVisibility(accessor);
15+
}
16+
</script>
17+
18+
<section class="max-w-5xl mx-auto my-8 px-4">
19+
<h2 class="text-2xl font-bold mb-6 text-gray-800 border-b pb-2">Column Visibility</h2>
20+
21+
<div class="mb-6">
22+
<p class="text-sm text-gray-600 mb-3">Select which columns to display in the table:</p>
23+
<div class="flex flex-wrap gap-2">
24+
{#each visibilityTable.columns as column}
25+
<button
26+
class="px-4 py-2 rounded-md font-medium text-sm transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500
27+
{column.visible
28+
? 'bg-emerald-100 text-emerald-800 border border-emerald-300 hover:bg-emerald-200'
29+
: 'bg-gray-100 text-gray-600 border border-gray-200 hover:bg-gray-200'}"
30+
onclick={() => toggleColumn(column.accessor)}
31+
>
32+
<div class="flex items-center gap-2">
33+
<span class="w-4 h-4 flex items-center justify-center">
34+
{#if column.visible}
35+
<svg
36+
xmlns="http://www.w3.org/2000/svg"
37+
viewBox="0 0 20 20"
38+
fill="currentColor"
39+
class="w-4 h-4"
40+
>
41+
<path
42+
fill-rule="evenodd"
43+
d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
44+
clip-rule="evenodd"
45+
/>
46+
</svg>
47+
{:else}
48+
<svg
49+
xmlns="http://www.w3.org/2000/svg"
50+
viewBox="0 0 20 20"
51+
fill="currentColor"
52+
class="w-4 h-4"
53+
>
54+
<path
55+
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
56+
/>
57+
</svg>
58+
{/if}
59+
</span>
60+
{column.accessor.charAt(0).toUpperCase() + column.accessor.slice(1)}
61+
</div>
62+
</button>
63+
{/each}
64+
</div>
65+
</div>
66+
67+
<div class="bg-white rounded-lg shadow-md overflow-hidden border border-gray-200">
68+
<div class="overflow-x-auto">
69+
<table class="w-full">
70+
<thead>
71+
<tr class="bg-gray-50 border-b border-gray-200">
72+
{#each visibilityTable.headers as header}
73+
<th
74+
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
75+
>{header}</th
76+
>
77+
{/each}
78+
</tr>
79+
</thead>
80+
<tbody class="divide-y divide-gray-200">
81+
{#each visibilityTable.rows as row}
82+
<tr class="hover:bg-gray-50 transition-colors duration-150 ease-in-out">
83+
{#each row.cells as cell}
84+
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{cell.value}</td>
85+
{/each}
86+
</tr>
87+
{/each}
88+
{#if visibilityTable.rows.length === 0}
89+
<tr>
90+
<td
91+
colspan={visibilityTable.headers.length}
92+
class="px-6 py-8 text-center text-sm text-gray-500"
93+
>
94+
No data available
95+
</td>
96+
</tr>
97+
{/if}
98+
</tbody>
99+
</table>
100+
</div>
101+
</div>
102+
</section>

0 commit comments

Comments
 (0)