@smicolon/ai-kit 0.3.2 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/README.md +73 -40
  2. package/dist/index.js +312 -127
  3. package/package.json +5 -5
  4. package/.claude-plugin/marketplace.json +0 -369
  5. package/packs/architect/CHANGELOG.md +0 -17
  6. package/packs/architect/README.md +0 -58
  7. package/packs/architect/agents/system-architect.md +0 -768
  8. package/packs/architect/commands/diagram-create.md +0 -300
  9. package/packs/better-auth/.mcp.json +0 -14
  10. package/packs/better-auth/CHANGELOG.md +0 -26
  11. package/packs/better-auth/README.md +0 -125
  12. package/packs/better-auth/agents/auth-architect.md +0 -278
  13. package/packs/better-auth/commands/auth-provider-add.md +0 -265
  14. package/packs/better-auth/commands/auth-setup.md +0 -298
  15. package/packs/better-auth/skills/auth-security/SKILL.md +0 -425
  16. package/packs/better-auth/skills/better-auth-patterns/SKILL.md +0 -455
  17. package/packs/dev-loop/CHANGELOG.md +0 -69
  18. package/packs/dev-loop/README.md +0 -155
  19. package/packs/dev-loop/commands/cancel-dev.md +0 -21
  20. package/packs/dev-loop/commands/dev-loop.md +0 -72
  21. package/packs/dev-loop/commands/dev-plan.md +0 -351
  22. package/packs/dev-loop/hooks/hooks.json +0 -15
  23. package/packs/dev-loop/hooks/stop-hook.sh +0 -178
  24. package/packs/dev-loop/scripts/setup-dev-loop.sh +0 -194
  25. package/packs/dev-loop/skills/tdd-planner/SKILL.md +0 -249
  26. package/packs/dev-loop/skills/tdd-planner/references/framework-patterns.md +0 -874
  27. package/packs/dev-loop/skills/tdd-planner/references/good-example.md +0 -260
  28. package/packs/dev-loop/skills/tdd-planner/references/plan-template.md +0 -275
  29. package/packs/django/CHANGELOG.md +0 -39
  30. package/packs/django/README.md +0 -92
  31. package/packs/django/agents/django-architect.md +0 -182
  32. package/packs/django/agents/django-builder.md +0 -250
  33. package/packs/django/agents/django-feature-based.md +0 -420
  34. package/packs/django/agents/django-reviewer.md +0 -253
  35. package/packs/django/agents/django-tester.md +0 -230
  36. package/packs/django/commands/api-endpoint.md +0 -285
  37. package/packs/django/commands/model-create.md +0 -178
  38. package/packs/django/commands/test-generate.md +0 -325
  39. package/packs/django/rules/migrations.md +0 -138
  40. package/packs/django/rules/models.md +0 -167
  41. package/packs/django/rules/serializers.md +0 -126
  42. package/packs/django/rules/services.md +0 -131
  43. package/packs/django/rules/tests.md +0 -140
  44. package/packs/django/rules/views.md +0 -102
  45. package/packs/django/skills/import-convention-enforcer/SKILL.md +0 -226
  46. package/packs/django/skills/import-convention-enforcer/patterns/django-imports.md +0 -343
  47. package/packs/django/skills/migration-safety-checker/SKILL.md +0 -375
  48. package/packs/django/skills/model-entity-validator/SKILL.md +0 -298
  49. package/packs/django/skills/performance-optimizer/SKILL.md +0 -447
  50. package/packs/django/skills/red-phase-verifier/SKILL.md +0 -180
  51. package/packs/django/skills/security-first-validator/SKILL.md +0 -435
  52. package/packs/django/skills/test-coverage-advisor/SKILL.md +0 -394
  53. package/packs/django/skills/test-validity-checker/SKILL.md +0 -194
  54. package/packs/failure-log/CHANGELOG.md +0 -20
  55. package/packs/failure-log/README.md +0 -168
  56. package/packs/failure-log/commands/failure-add.md +0 -106
  57. package/packs/failure-log/commands/failure-list.md +0 -89
  58. package/packs/failure-log/hooks/hooks.json +0 -16
  59. package/packs/failure-log/hooks/scripts/inject-failures.sh +0 -64
  60. package/packs/failure-log/skills/failure-log-manager/SKILL.md +0 -164
  61. package/packs/flutter/CHANGELOG.md +0 -19
  62. package/packs/flutter/README.md +0 -170
  63. package/packs/flutter/agents/flutter-architect.md +0 -166
  64. package/packs/flutter/agents/flutter-builder.md +0 -303
  65. package/packs/flutter/agents/release-manager.md +0 -355
  66. package/packs/flutter/commands/fastlane-setup.md +0 -188
  67. package/packs/flutter/commands/flutter-build.md +0 -90
  68. package/packs/flutter/commands/flutter-deploy.md +0 -133
  69. package/packs/flutter/commands/flutter-test.md +0 -117
  70. package/packs/flutter/commands/signing-setup.md +0 -209
  71. package/packs/flutter/hooks/hooks.json +0 -17
  72. package/packs/flutter/skills/fastlane-knowledge/SKILL.md +0 -193
  73. package/packs/flutter/skills/flutter-architecture/SKILL.md +0 -127
  74. package/packs/flutter/skills/store-publishing/SKILL.md +0 -163
  75. package/packs/hono/CHANGELOG.md +0 -19
  76. package/packs/hono/README.md +0 -143
  77. package/packs/hono/agents/hono-architect.md +0 -240
  78. package/packs/hono/agents/hono-builder.md +0 -285
  79. package/packs/hono/agents/hono-reviewer.md +0 -279
  80. package/packs/hono/agents/hono-tester.md +0 -346
  81. package/packs/hono/commands/middleware-create.md +0 -223
  82. package/packs/hono/commands/project-init.md +0 -306
  83. package/packs/hono/commands/route-create.md +0 -153
  84. package/packs/hono/commands/rpc-client.md +0 -263
  85. package/packs/hono/skills/cloudflare-bindings/SKILL.md +0 -408
  86. package/packs/hono/skills/hono-patterns/SKILL.md +0 -309
  87. package/packs/hono/skills/rpc-typesafe/SKILL.md +0 -388
  88. package/packs/hono/skills/zod-validation/SKILL.md +0 -332
  89. package/packs/nestjs/CHANGELOG.md +0 -29
  90. package/packs/nestjs/README.md +0 -75
  91. package/packs/nestjs/agents/nestjs-architect.md +0 -402
  92. package/packs/nestjs/agents/nestjs-builder.md +0 -301
  93. package/packs/nestjs/agents/nestjs-tester.md +0 -437
  94. package/packs/nestjs/commands/module-create.md +0 -369
  95. package/packs/nestjs/rules/controllers.md +0 -92
  96. package/packs/nestjs/rules/dto.md +0 -124
  97. package/packs/nestjs/rules/entities.md +0 -102
  98. package/packs/nestjs/rules/services.md +0 -106
  99. package/packs/nestjs/skills/barrel-export-manager/SKILL.md +0 -389
  100. package/packs/nestjs/skills/import-convention-enforcer/SKILL.md +0 -365
  101. package/packs/nextjs/CHANGELOG.md +0 -36
  102. package/packs/nextjs/README.md +0 -76
  103. package/packs/nextjs/agents/frontend-tester.md +0 -680
  104. package/packs/nextjs/agents/frontend-visual.md +0 -820
  105. package/packs/nextjs/agents/nextjs-architect.md +0 -331
  106. package/packs/nextjs/agents/nextjs-modular.md +0 -433
  107. package/packs/nextjs/commands/component-create.md +0 -398
  108. package/packs/nextjs/rules/api-routes.md +0 -129
  109. package/packs/nextjs/rules/components.md +0 -106
  110. package/packs/nextjs/rules/hooks.md +0 -132
  111. package/packs/nextjs/skills/accessibility-validator/SKILL.md +0 -445
  112. package/packs/nextjs/skills/import-convention-enforcer/SKILL.md +0 -399
  113. package/packs/nextjs/skills/react-form-validator/SKILL.md +0 -569
  114. package/packs/nuxtjs/CHANGELOG.md +0 -30
  115. package/packs/nuxtjs/README.md +0 -56
  116. package/packs/nuxtjs/agents/frontend-tester.md +0 -680
  117. package/packs/nuxtjs/agents/frontend-visual.md +0 -820
  118. package/packs/nuxtjs/agents/nuxtjs-architect.md +0 -537
  119. package/packs/nuxtjs/commands/component-create.md +0 -223
  120. package/packs/nuxtjs/rules/components.md +0 -101
  121. package/packs/nuxtjs/rules/composables.md +0 -118
  122. package/packs/nuxtjs/rules/server-routes.md +0 -127
  123. package/packs/nuxtjs/skills/accessibility-validator/SKILL.md +0 -183
  124. package/packs/nuxtjs/skills/import-convention-enforcer/SKILL.md +0 -196
  125. package/packs/nuxtjs/skills/veevalidate-form-validator/SKILL.md +0 -190
  126. package/packs/onboard/CHANGELOG.md +0 -22
  127. package/packs/onboard/README.md +0 -103
  128. package/packs/onboard/agents/onboard-guide.md +0 -118
  129. package/packs/onboard/commands/onboard.md +0 -313
  130. package/packs/onboard/skills/onboard-context-provider/SKILL.md +0 -98
  131. package/packs/tanstack-router/CHANGELOG.md +0 -30
  132. package/packs/tanstack-router/README.md +0 -113
  133. package/packs/tanstack-router/agents/tanstack-architect.md +0 -173
  134. package/packs/tanstack-router/agents/tanstack-builder.md +0 -360
  135. package/packs/tanstack-router/agents/tanstack-tester.md +0 -454
  136. package/packs/tanstack-router/commands/form-create.md +0 -313
  137. package/packs/tanstack-router/commands/query-create.md +0 -263
  138. package/packs/tanstack-router/commands/route-create.md +0 -190
  139. package/packs/tanstack-router/commands/table-create.md +0 -413
  140. package/packs/tanstack-router/skills/ai-patterns/SKILL.md +0 -370
  141. package/packs/tanstack-router/skills/db-patterns/SKILL.md +0 -346
  142. package/packs/tanstack-router/skills/devtools-patterns/SKILL.md +0 -415
  143. package/packs/tanstack-router/skills/form-patterns/SKILL.md +0 -425
  144. package/packs/tanstack-router/skills/pacer-patterns/SKILL.md +0 -341
  145. package/packs/tanstack-router/skills/query-patterns/SKILL.md +0 -359
  146. package/packs/tanstack-router/skills/router-patterns/SKILL.md +0 -285
  147. package/packs/tanstack-router/skills/store-patterns/SKILL.md +0 -351
  148. package/packs/tanstack-router/skills/table-patterns/SKILL.md +0 -531
  149. package/packs/tanstack-router/skills/tanstack-conventions/SKILL.md +0 -428
  150. package/packs/tanstack-router/skills/virtual-patterns/SKILL.md +0 -490
  151. package/packs/worktree/CHANGELOG.md +0 -45
  152. package/packs/worktree/README.md +0 -219
  153. package/packs/worktree/commands/wt.md +0 -93
  154. package/packs/worktree/scripts/wt.sh +0 -957
  155. package/packs/worktree/skills/worktree-manager/SKILL.md +0 -113
@@ -1,531 +0,0 @@
1
- ---
2
- name: TanStack Table Patterns
3
- description: >-
4
- Auto-enforce TanStack Table best practices for headless data tables. Activates
5
- when creating tables, implementing sorting, filtering, pagination, or building
6
- data grids in React applications.
7
- version: 1.0.0
8
- ---
9
-
10
- # TanStack Table Patterns
11
-
12
- This skill enforces TanStack Table best practices for headless, type-safe data tables.
13
-
14
- ## Basic Table Setup
15
-
16
- ```typescript
17
- import {
18
- createColumnHelper,
19
- useReactTable,
20
- getCoreRowModel,
21
- flexRender,
22
- } from '@tanstack/react-table'
23
- import type { Post } from '@/features/posts/types'
24
-
25
- const columnHelper = createColumnHelper<Post>()
26
-
27
- const columns = [
28
- columnHelper.accessor('title', {
29
- header: 'Title',
30
- cell: (info) => info.getValue(),
31
- }),
32
- columnHelper.accessor('author.name', {
33
- header: 'Author',
34
- cell: (info) => info.getValue(),
35
- }),
36
- columnHelper.accessor('createdAt', {
37
- header: 'Created',
38
- cell: (info) => new Date(info.getValue()).toLocaleDateString(),
39
- }),
40
- columnHelper.display({
41
- id: 'actions',
42
- header: 'Actions',
43
- cell: ({ row }) => <PostActions post={row.original} />,
44
- }),
45
- ]
46
-
47
- export function PostsTable({ data }: { data: Post[] }) {
48
- const table = useReactTable({
49
- data,
50
- columns,
51
- getCoreRowModel: getCoreRowModel(),
52
- })
53
-
54
- return (
55
- <table>
56
- <thead>
57
- {table.getHeaderGroups().map((headerGroup) => (
58
- <tr key={headerGroup.id}>
59
- {headerGroup.headers.map((header) => (
60
- <th key={header.id}>
61
- {header.isPlaceholder
62
- ? null
63
- : flexRender(header.column.columnDef.header, header.getContext())}
64
- </th>
65
- ))}
66
- </tr>
67
- ))}
68
- </thead>
69
- <tbody>
70
- {table.getRowModel().rows.map((row) => (
71
- <tr key={row.id}>
72
- {row.getVisibleCells().map((cell) => (
73
- <td key={cell.id}>
74
- {flexRender(cell.column.columnDef.cell, cell.getContext())}
75
- </td>
76
- ))}
77
- </tr>
78
- ))}
79
- </tbody>
80
- </table>
81
- )
82
- }
83
- ```
84
-
85
- ## Sorting
86
-
87
- ```typescript
88
- import {
89
- useReactTable,
90
- getCoreRowModel,
91
- getSortedRowModel,
92
- type SortingState,
93
- } from '@tanstack/react-table'
94
- import { useState } from 'react'
95
-
96
- export function SortableTable({ data }: { data: Post[] }) {
97
- const [sorting, setSorting] = useState<SortingState>([])
98
-
99
- const columns = [
100
- columnHelper.accessor('title', {
101
- header: ({ column }) => (
102
- <button
103
- onClick={() => column.toggleSorting()}
104
- className="flex items-center gap-1"
105
- >
106
- Title
107
- {column.getIsSorted() === 'asc' ? ' ↑' : column.getIsSorted() === 'desc' ? ' ↓' : ''}
108
- </button>
109
- ),
110
- cell: (info) => info.getValue(),
111
- }),
112
- // More columns...
113
- ]
114
-
115
- const table = useReactTable({
116
- data,
117
- columns,
118
- state: { sorting },
119
- onSortingChange: setSorting,
120
- getCoreRowModel: getCoreRowModel(),
121
- getSortedRowModel: getSortedRowModel(),
122
- })
123
-
124
- return (/* table JSX */)
125
- }
126
- ```
127
-
128
- ## Filtering
129
-
130
- ### Global Filter
131
- ```typescript
132
- import {
133
- useReactTable,
134
- getCoreRowModel,
135
- getFilteredRowModel,
136
- type ColumnFiltersState,
137
- } from '@tanstack/react-table'
138
-
139
- export function FilterableTable({ data }: { data: Post[] }) {
140
- const [globalFilter, setGlobalFilter] = useState('')
141
-
142
- const table = useReactTable({
143
- data,
144
- columns,
145
- state: { globalFilter },
146
- onGlobalFilterChange: setGlobalFilter,
147
- getCoreRowModel: getCoreRowModel(),
148
- getFilteredRowModel: getFilteredRowModel(),
149
- })
150
-
151
- return (
152
- <div>
153
- <input
154
- type="search"
155
- placeholder="Search all columns..."
156
- value={globalFilter}
157
- onChange={(e) => setGlobalFilter(e.target.value)}
158
- />
159
- {/* table JSX */}
160
- </div>
161
- )
162
- }
163
- ```
164
-
165
- ### Column Filters
166
- ```typescript
167
- import { useState } from 'react'
168
- import type { ColumnFiltersState } from '@tanstack/react-table'
169
-
170
- export function ColumnFilterTable({ data }: { data: Post[] }) {
171
- const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([])
172
-
173
- const columns = [
174
- columnHelper.accessor('status', {
175
- header: 'Status',
176
- cell: (info) => info.getValue(),
177
- filterFn: 'equals',
178
- }),
179
- // More columns...
180
- ]
181
-
182
- const table = useReactTable({
183
- data,
184
- columns,
185
- state: { columnFilters },
186
- onColumnFiltersChange: setColumnFilters,
187
- getCoreRowModel: getCoreRowModel(),
188
- getFilteredRowModel: getFilteredRowModel(),
189
- })
190
-
191
- return (
192
- <div>
193
- <select
194
- onChange={(e) =>
195
- table.getColumn('status')?.setFilterValue(e.target.value || undefined)
196
- }
197
- >
198
- <option value="">All statuses</option>
199
- <option value="draft">Draft</option>
200
- <option value="published">Published</option>
201
- </select>
202
- {/* table JSX */}
203
- </div>
204
- )
205
- }
206
- ```
207
-
208
- ## Pagination
209
-
210
- ### Client-Side Pagination
211
- ```typescript
212
- import {
213
- useReactTable,
214
- getCoreRowModel,
215
- getPaginationRowModel,
216
- } from '@tanstack/react-table'
217
-
218
- export function PaginatedTable({ data }: { data: Post[] }) {
219
- const table = useReactTable({
220
- data,
221
- columns,
222
- getCoreRowModel: getCoreRowModel(),
223
- getPaginationRowModel: getPaginationRowModel(),
224
- initialState: {
225
- pagination: { pageSize: 10 },
226
- },
227
- })
228
-
229
- return (
230
- <div>
231
- {/* table JSX */}
232
- <div className="pagination">
233
- <button
234
- onClick={() => table.previousPage()}
235
- disabled={!table.getCanPreviousPage()}
236
- >
237
- Previous
238
- </button>
239
- <span>
240
- Page {table.getState().pagination.pageIndex + 1} of{' '}
241
- {table.getPageCount()}
242
- </span>
243
- <button
244
- onClick={() => table.nextPage()}
245
- disabled={!table.getCanNextPage()}
246
- >
247
- Next
248
- </button>
249
- <select
250
- value={table.getState().pagination.pageSize}
251
- onChange={(e) => table.setPageSize(Number(e.target.value))}
252
- >
253
- {[10, 20, 50].map((size) => (
254
- <option key={size} value={size}>
255
- Show {size}
256
- </option>
257
- ))}
258
- </select>
259
- </div>
260
- </div>
261
- )
262
- }
263
- ```
264
-
265
- ### Server-Side Pagination
266
- ```typescript
267
- import { useQuery } from '@tanstack/react-query'
268
- import { Route } from '@tanstack/react-router'
269
-
270
- export function ServerPaginatedTable() {
271
- const { page, pageSize } = Route.useSearch()
272
- const navigate = Route.useNavigate()
273
-
274
- const { data, isLoading } = useQuery({
275
- queryKey: queryKeys.posts.list({ page, pageSize }),
276
- queryFn: () => postApi.getPosts({ page, pageSize }),
277
- })
278
-
279
- const table = useReactTable({
280
- data: data?.items ?? [],
281
- columns,
282
- pageCount: data?.pageCount ?? -1,
283
- state: {
284
- pagination: { pageIndex: page - 1, pageSize },
285
- },
286
- onPaginationChange: (updater) => {
287
- const newState =
288
- typeof updater === 'function'
289
- ? updater({ pageIndex: page - 1, pageSize })
290
- : updater
291
- navigate({
292
- search: (prev) => ({
293
- ...prev,
294
- page: newState.pageIndex + 1,
295
- pageSize: newState.pageSize,
296
- }),
297
- })
298
- },
299
- getCoreRowModel: getCoreRowModel(),
300
- manualPagination: true,
301
- })
302
-
303
- if (isLoading) return <Skeleton />
304
-
305
- return (/* table with pagination controls */)
306
- }
307
- ```
308
-
309
- ## Row Selection
310
-
311
- ```typescript
312
- import {
313
- useReactTable,
314
- getCoreRowModel,
315
- type RowSelectionState,
316
- } from '@tanstack/react-table'
317
-
318
- export function SelectableTable({ data, onSelectionChange }: Props) {
319
- const [rowSelection, setRowSelection] = useState<RowSelectionState>({})
320
-
321
- const columns = [
322
- columnHelper.display({
323
- id: 'select',
324
- header: ({ table }) => (
325
- <input
326
- type="checkbox"
327
- checked={table.getIsAllRowsSelected()}
328
- onChange={table.getToggleAllRowsSelectedHandler()}
329
- />
330
- ),
331
- cell: ({ row }) => (
332
- <input
333
- type="checkbox"
334
- checked={row.getIsSelected()}
335
- onChange={row.getToggleSelectedHandler()}
336
- />
337
- ),
338
- }),
339
- // Other columns...
340
- ]
341
-
342
- const table = useReactTable({
343
- data,
344
- columns,
345
- state: { rowSelection },
346
- onRowSelectionChange: setRowSelection,
347
- getCoreRowModel: getCoreRowModel(),
348
- enableRowSelection: true,
349
- })
350
-
351
- // Get selected rows
352
- const selectedRows = table.getSelectedRowModel().rows.map((row) => row.original)
353
-
354
- return (
355
- <div>
356
- <span>{selectedRows.length} selected</span>
357
- {/* table JSX */}
358
- </div>
359
- )
360
- }
361
- ```
362
-
363
- ## Column Visibility
364
-
365
- ```typescript
366
- import { useState } from 'react'
367
- import type { VisibilityState } from '@tanstack/react-table'
368
-
369
- export function ColumnVisibilityTable({ data }: { data: Post[] }) {
370
- const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({})
371
-
372
- const table = useReactTable({
373
- data,
374
- columns,
375
- state: { columnVisibility },
376
- onColumnVisibilityChange: setColumnVisibility,
377
- getCoreRowModel: getCoreRowModel(),
378
- })
379
-
380
- return (
381
- <div>
382
- <div className="column-toggles">
383
- {table.getAllLeafColumns().map((column) => (
384
- <label key={column.id}>
385
- <input
386
- type="checkbox"
387
- checked={column.getIsVisible()}
388
- onChange={column.getToggleVisibilityHandler()}
389
- />
390
- {column.id}
391
- </label>
392
- ))}
393
- </div>
394
- {/* table JSX */}
395
- </div>
396
- )
397
- }
398
- ```
399
-
400
- ## Complete Feature Table
401
-
402
- ```typescript
403
- import {
404
- createColumnHelper,
405
- useReactTable,
406
- getCoreRowModel,
407
- getSortedRowModel,
408
- getFilteredRowModel,
409
- getPaginationRowModel,
410
- flexRender,
411
- type SortingState,
412
- type ColumnFiltersState,
413
- } from '@tanstack/react-table'
414
- import { useState } from 'react'
415
-
416
- export function FullFeaturedTable<T>({
417
- data,
418
- columns,
419
- }: {
420
- data: T[]
421
- columns: ColumnDef<T>[]
422
- }) {
423
- const [sorting, setSorting] = useState<SortingState>([])
424
- const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([])
425
- const [globalFilter, setGlobalFilter] = useState('')
426
-
427
- const table = useReactTable({
428
- data,
429
- columns,
430
- state: {
431
- sorting,
432
- columnFilters,
433
- globalFilter,
434
- },
435
- onSortingChange: setSorting,
436
- onColumnFiltersChange: setColumnFilters,
437
- onGlobalFilterChange: setGlobalFilter,
438
- getCoreRowModel: getCoreRowModel(),
439
- getSortedRowModel: getSortedRowModel(),
440
- getFilteredRowModel: getFilteredRowModel(),
441
- getPaginationRowModel: getPaginationRowModel(),
442
- })
443
-
444
- return (
445
- <div className="table-container">
446
- {/* Search */}
447
- <input
448
- type="search"
449
- placeholder="Search..."
450
- value={globalFilter}
451
- onChange={(e) => setGlobalFilter(e.target.value)}
452
- />
453
-
454
- {/* Table */}
455
- <table>
456
- <thead>
457
- {table.getHeaderGroups().map((headerGroup) => (
458
- <tr key={headerGroup.id}>
459
- {headerGroup.headers.map((header) => (
460
- <th key={header.id}>
461
- {flexRender(header.column.columnDef.header, header.getContext())}
462
- </th>
463
- ))}
464
- </tr>
465
- ))}
466
- </thead>
467
- <tbody>
468
- {table.getRowModel().rows.map((row) => (
469
- <tr key={row.id}>
470
- {row.getVisibleCells().map((cell) => (
471
- <td key={cell.id}>
472
- {flexRender(cell.column.columnDef.cell, cell.getContext())}
473
- </td>
474
- ))}
475
- </tr>
476
- ))}
477
- </tbody>
478
- </table>
479
-
480
- {/* Pagination */}
481
- <div className="pagination">
482
- <button onClick={() => table.previousPage()} disabled={!table.getCanPreviousPage()}>
483
- Previous
484
- </button>
485
- <span>
486
- Page {table.getState().pagination.pageIndex + 1} of {table.getPageCount()}
487
- </span>
488
- <button onClick={() => table.nextPage()} disabled={!table.getCanNextPage()}>
489
- Next
490
- </button>
491
- </div>
492
- </div>
493
- )
494
- }
495
- ```
496
-
497
- ## Conventions to Enforce
498
-
499
- 1. **Column helper** - Use `createColumnHelper<T>()` for type safety
500
- 2. **FlexRender** - Always use `flexRender()` for headers and cells
501
- 3. **Stable columns** - Define columns outside component or memoize
502
- 4. **Server pagination** - Use `manualPagination: true` with API
503
- 5. **URL state** - Sync table state with router search params
504
- 6. **Accessibility** - Include proper table semantics and roles
505
-
506
- ## Anti-Patterns to Block
507
-
508
- ```typescript
509
- // ❌ WRONG: Columns inside component without memo
510
- function Table() {
511
- const columns = [/* columns recreated every render */]
512
- }
513
-
514
- // ✅ CORRECT: Columns outside or memoized
515
- const columns = [/* stable reference */]
516
- function Table() {
517
- const table = useReactTable({ columns, ... })
518
- }
519
-
520
- // ❌ WRONG: Not using flexRender
521
- <td>{cell.getValue()}</td>
522
-
523
- // ✅ CORRECT: Use flexRender
524
- <td>{flexRender(cell.column.columnDef.cell, cell.getContext())}</td>
525
-
526
- // ❌ WRONG: Hardcoded pagination
527
- const [page, setPage] = useState(1)
528
-
529
- // ✅ CORRECT: URL-synced pagination
530
- const { page } = Route.useSearch()
531
- ```