|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +This is a monorepo for `tanstack-table-search-params`, a React hook library that syncs TanStack Table state with URL search parameters. The library enables table state (sorting, filtering, pagination, etc.) to persist in the URL, making it shareable and bookmarkable. |
| 8 | + |
| 9 | +## Monorepo Structure |
| 10 | + |
| 11 | +- **`packages/tanstack-table-search-params/`**: Main library package (published to npm) |
| 12 | +- **`packages/tsconfig/`**: Shared TypeScript configuration |
| 13 | +- **`examples/`**: Example implementations for different routers: |
| 14 | + - `next-pages-router/`: Next.js Pages Router example |
| 15 | + - `next-app-router/`: Next.js App Router example |
| 16 | + - `tanstack-router/`: TanStack Router example |
| 17 | + - `react-router-lib/`: React Router example |
| 18 | + - `lib/`: Shared components used across examples |
| 19 | + |
| 20 | +## Development Commands |
| 21 | + |
| 22 | +### Build, Test, and Lint |
| 23 | + |
| 24 | +```bash |
| 25 | +# Build all packages and examples (uses Turbo) |
| 26 | +pnpm build |
| 27 | + |
| 28 | +# Type-check all packages |
| 29 | +pnpm type-check |
| 30 | + |
| 31 | +# Run tests (runs tests in main package) |
| 32 | +pnpm test |
| 33 | + |
| 34 | +# Lint and format with Biome |
| 35 | +pnpm check-write |
| 36 | + |
| 37 | +# Prettier formatting |
| 38 | +pnpm prettier |
| 39 | + |
| 40 | +# Check for unused dependencies |
| 41 | +pnpm knip |
| 42 | +``` |
| 43 | + |
| 44 | +### Working with Specific Packages |
| 45 | + |
| 46 | +```bash |
| 47 | +# Main package commands |
| 48 | +pnpm tanstack-table-search-params <command> |
| 49 | +pnpm tanstack-table-search-params build |
| 50 | +pnpm tanstack-table-search-params test |
| 51 | +pnpm tanstack-table-search-params type-check |
| 52 | + |
| 53 | +# Example project commands |
| 54 | +pnpm examples/next-pages-router <command> |
| 55 | +pnpm examples/next-app-router <command> |
| 56 | +pnpm examples/tanstack-router <command> |
| 57 | +pnpm examples/react-router-lib <command> |
| 58 | +``` |
| 59 | + |
| 60 | +### Testing |
| 61 | + |
| 62 | +```bash |
| 63 | +# Run tests in watch mode |
| 64 | +cd packages/tanstack-table-search-params |
| 65 | +pnpm test |
| 66 | + |
| 67 | +# Run specific test file |
| 68 | +pnpm test src/tests/globalFilter.test.ts |
| 69 | +``` |
| 70 | + |
| 71 | +## Architecture |
| 72 | + |
| 73 | +### Main Hook: `useTableSearchParams` |
| 74 | + |
| 75 | +The core export is `useTableSearchParams`, which orchestrates multiple state-specific hooks: |
| 76 | + |
| 77 | +1. **State-specific hooks** (e.g., `useGlobalFilter`, `useSorting`, `usePagination`): |
| 78 | + - Each manages one TanStack Table state |
| 79 | + - Decodes query params → state |
| 80 | + - Encodes state → query params |
| 81 | + - Handles debouncing via `useDebounce` |
| 82 | + - Returns state, onChange handler, and encoder function |
| 83 | + |
| 84 | +2. **Main hook** (`useTableSearchParams`): |
| 85 | + - Composes all state-specific hooks |
| 86 | + - Manages enabled/disabled states |
| 87 | + - Provides `onStateChange` for batch updates |
| 88 | + - Returns partial TableState + onChange handlers |
| 89 | + |
| 90 | +### Encoder/Decoder Pattern |
| 91 | + |
| 92 | +Each table state has paired encoder/decoder functions in `src/encoder-decoder/`: |
| 93 | + |
| 94 | +- **Decoders**: `Query → State` (e.g., `"desc"` → `[{id: "name", desc: true}]`) |
| 95 | +- **Encoders**: `State → Query` (e.g., `[{id: "name", desc: true}]` → `"sorting.name"`) |
| 96 | +- Default implementations can be customized via options |
| 97 | +- Exported separately for preset query params on navigation |
| 98 | + |
| 99 | +### Router Abstraction |
| 100 | + |
| 101 | +The library is router-agnostic via the `Router` type (`src/types.ts`): |
| 102 | + |
| 103 | +```typescript |
| 104 | +type Router = { |
| 105 | + query: Query; // Current query params |
| 106 | + navigate(url): void; // Navigation function (push or replace) |
| 107 | + pathname: string; // Current pathname |
| 108 | +}; |
| 109 | +``` |
| 110 | + |
| 111 | +### Query Update Flow |
| 112 | + |
| 113 | +1. User interacts with table → TanStack Table calls onChange handler |
| 114 | +2. onChange handler in state-specific hook: |
| 115 | + - Encodes new state to query params |
| 116 | + - Calls `updateQuery()` to merge with existing query |
| 117 | +3. `updateQuery()` builds new URL and calls router's navigate function |
| 118 | +4. Router updates URL → query params change → hook re-renders with new decoded state |
| 119 | + |
| 120 | +## Testing Strategy |
| 121 | + |
| 122 | +Tests are organized in `packages/tanstack-table-search-params/src/tests/`: |
| 123 | + |
| 124 | +- **General tests**: Test with generic router mock (`testRouter.ts`) |
| 125 | +- **`next-pages-router/` tests**: Test Next.js-specific behavior with `next-router-mock` |
| 126 | +- Each state has its own test file (e.g., `globalFilter.test.ts`, `sorting.test.ts`) |
| 127 | +- Tests verify encoding/decoding, debouncing, and custom options |
| 128 | + |
| 129 | +## Key Implementation Details |
| 130 | + |
| 131 | +- **Supported states**: globalFilter, sorting, pagination, columnFilters, columnOrder, rowSelection, columnVisibility |
| 132 | +- **Default encoding**: Most states use array notation (e.g., `sorting.0.id=name&sorting.0.desc=true`) |
| 133 | +- **Debouncing**: Optional per-state debouncing via `useDebounce` hook |
| 134 | +- **Custom encoders/decoders**: Users can provide custom encoding logic (e.g., JSON, flat params) |
| 135 | +- **Dual exports**: Main hook from `"tanstack-table-search-params"`, encoders from `"tanstack-table-search-params/encoder-decoder"` |
| 136 | + |
| 137 | +## Build Configuration |
| 138 | + |
| 139 | +- **Builder**: tsup (`tsup.config.ts`) |
| 140 | +- **Entry points**: `src/index.ts` (main hook), `src/encoder-decoder/index.ts` (encoder/decoder exports) |
| 141 | +- **Output formats**: CJS and ESM |
| 142 | +- **Target**: `esnext` |
| 143 | +- TypeScript declarations generated automatically |
0 commit comments