@toniel/laravel-tanstack-pagination 0.1.0 → 0.1.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.
- package/LICENSE +21 -0
- package/README.md +314 -31
- package/package.json +15 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Toniel
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,23 +1,51 @@
|
|
|
1
1
|
# Laravel TanStack Pagination
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@toniel/laravel-tanstack-pagination)
|
|
4
|
+
[](https://www.npmjs.com/package/@toniel/laravel-tanstack-pagination)
|
|
5
|
+
[](https://github.com/toniel/laravel-tanstack-pagination/blob/main/LICENSE)
|
|
6
|
+
[](https://github.com/toniel/laravel-tanstack-pagination)
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
Vue 3 composables untuk Laravel pagination dengan TanStack Query - **Headless & Framework Agnostic**.
|
|
9
|
+
|
|
10
|
+
> 💡 **Looking for ready-to-use UI components?** Check out [`@toniel/laravel-tanstack-datatable`](https://github.com/toniel/laravel-tanstack-datatable) - Pre-built DataTable components with this library.
|
|
11
|
+
|
|
12
|
+
## 📦 Installation
|
|
6
13
|
|
|
7
14
|
```bash
|
|
8
15
|
npm install @toniel/laravel-tanstack-pagination
|
|
16
|
+
# or
|
|
17
|
+
yarn add @toniel/laravel-tanstack-pagination
|
|
18
|
+
# or
|
|
19
|
+
pnpm add @toniel/laravel-tanstack-pagination
|
|
20
|
+
# or
|
|
21
|
+
bun add @toniel/laravel-tanstack-pagination
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Peer Dependencies
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install vue @tanstack/vue-query
|
|
9
28
|
```
|
|
10
29
|
|
|
11
|
-
##
|
|
30
|
+
## 🚀 Quick Start
|
|
12
31
|
|
|
13
32
|
```typescript
|
|
14
33
|
import { usePagination } from '@toniel/laravel-tanstack-pagination'
|
|
34
|
+
import axios from 'axios'
|
|
15
35
|
|
|
16
36
|
const {
|
|
17
37
|
tableData,
|
|
18
38
|
pagination,
|
|
39
|
+
search,
|
|
40
|
+
currentPerPage,
|
|
41
|
+
sortBy,
|
|
42
|
+
sortDirection,
|
|
43
|
+
isLoading,
|
|
44
|
+
error,
|
|
19
45
|
handlePageChange,
|
|
20
|
-
|
|
46
|
+
handlePerPageChange,
|
|
47
|
+
handleSearchChange,
|
|
48
|
+
handleSortChange,
|
|
21
49
|
} = usePagination(
|
|
22
50
|
(filters) => axios.get('/api/users', { params: filters }),
|
|
23
51
|
{
|
|
@@ -27,47 +55,302 @@ const {
|
|
|
27
55
|
)
|
|
28
56
|
```
|
|
29
57
|
|
|
30
|
-
## Features
|
|
58
|
+
## ✨ Features
|
|
31
59
|
|
|
32
|
-
- ✅
|
|
33
|
-
- ✅
|
|
34
|
-
- ✅
|
|
35
|
-
- ✅
|
|
36
|
-
- ✅
|
|
37
|
-
- ✅
|
|
60
|
+
- ✅ **Headless** - Bring your own UI components
|
|
61
|
+
- ✅ **Laravel pagination** support out of the box
|
|
62
|
+
- ✅ **TanStack Query** integration for caching & refetching
|
|
63
|
+
- ✅ **Search** with automatic debounce
|
|
64
|
+
- ✅ **Sorting** (server-side)
|
|
65
|
+
- ✅ **Filtering** with flexible API
|
|
66
|
+
- ✅ **Table numbering** helper for sequential row numbers
|
|
67
|
+
- ✅ **TypeScript** fully typed
|
|
68
|
+
- ✅ **Framework agnostic** - Works with any UI library
|
|
38
69
|
|
|
39
|
-
## API
|
|
70
|
+
## 📖 API Reference
|
|
40
71
|
|
|
41
72
|
### `usePagination(fetchFn, options)`
|
|
42
73
|
|
|
43
74
|
Main composable for handling Laravel pagination.
|
|
44
75
|
|
|
45
76
|
**Parameters:**
|
|
46
|
-
- `fetchFn`:
|
|
47
|
-
-
|
|
48
|
-
|
|
49
|
-
- `
|
|
77
|
+
- `fetchFn`: `(filters: PaginationFilters) => Promise<LaravelPaginationResponse<T>>`
|
|
78
|
+
- Function that fetches data from Laravel API
|
|
79
|
+
- `options`: `UsePaginationOptions<T>`
|
|
80
|
+
- `queryKey`: `string` - Unique key for the query (required)
|
|
81
|
+
- `defaultPerPage`: `number` - Items per page (default: `10`)
|
|
82
|
+
- `defaultSearch`: `string` - Default search query (default: `''`)
|
|
83
|
+
- `defaultSort`: `SortState` - Default sort state (default: `null`)
|
|
84
|
+
- ...all other TanStack Query options
|
|
50
85
|
|
|
51
86
|
**Returns:**
|
|
52
|
-
- `tableData`: Computed array of data items
|
|
53
|
-
- `pagination`: Reactive pagination state
|
|
54
|
-
- `handlePageChange`: Function to change page
|
|
55
|
-
- `handleSearchChange`: Function to handle search input
|
|
56
|
-
- `handleSortChange`: Function to handle sorting
|
|
57
|
-
- `isLoading`: Loading state
|
|
58
|
-
- `error`: Error state
|
|
59
87
|
|
|
60
|
-
|
|
88
|
+
| Property | Type | Description |
|
|
89
|
+
|----------|------|-------------|
|
|
90
|
+
| `tableData` | `Ref<T[]>` | Computed array of data items |
|
|
91
|
+
| `pagination` | `Ref<LaravelPaginationResponse \| null>` | Full Laravel pagination response |
|
|
92
|
+
| `currentPage` | `Ref<number>` | Current page number |
|
|
93
|
+
| `perPage` | `Ref<number>` | Items per page |
|
|
94
|
+
| `search` | `Ref<string>` | Current search query |
|
|
95
|
+
| `sortBy` | `Ref<string \| null>` | Current sort column |
|
|
96
|
+
| `sortDirection` | `Ref<'asc' \| 'desc'>` | Sort direction |
|
|
97
|
+
| `filters` | `ComputedRef<PaginationFilters>` | All active filters |
|
|
98
|
+
| `isLoading` | `Ref<boolean>` | Loading state from TanStack Query |
|
|
99
|
+
| `error` | `Ref<Error \| null>` | Error state from TanStack Query |
|
|
100
|
+
| `handlePageChange` | `(page: number) => void` | Change page handler |
|
|
101
|
+
| `handlePerPageChange` | `(perPage: number) => void` | Change per page handler |
|
|
102
|
+
| `handleSearchChange` | `(search: string) => void` | Search change handler (debounced) |
|
|
103
|
+
| `handleSortChange` | `(column: string) => void` | Toggle sort on column |
|
|
104
|
+
| `setFilter` | `(key: string, value: any) => void` | Add custom filter |
|
|
105
|
+
| `removeFilter` | `(key: string) => void` | Remove custom filter |
|
|
106
|
+
| `resetFilters` | `() => void` | Reset all filters to defaults |
|
|
107
|
+
| `getNumberingColumn` | `(options?) => ColumnDef` | Get numbering column for TanStack Table |
|
|
108
|
+
| `refetch` | TanStack Query refetch function |
|
|
109
|
+
| `...queryResult` | All other TanStack Query return values |
|
|
61
110
|
|
|
62
|
-
|
|
111
|
+
### `useTableNumbering()`
|
|
63
112
|
|
|
64
|
-
|
|
65
|
-
- `currentPage`: Current page number
|
|
66
|
-
- `perPage`: Items per page
|
|
113
|
+
Helper composable for creating table row numbering columns.
|
|
67
114
|
|
|
68
115
|
**Returns:**
|
|
69
|
-
- `
|
|
116
|
+
- `createNumberingColumn(pagination, perPage, options?)`: Function to create a numbering column definition for TanStack Table
|
|
117
|
+
|
|
118
|
+
**Example:**
|
|
119
|
+
```ts
|
|
120
|
+
const { createNumberingColumn } = useTableNumbering()
|
|
121
|
+
|
|
122
|
+
const numberingColumn = createNumberingColumn(
|
|
123
|
+
pagination, // ref from usePagination
|
|
124
|
+
perPage, // ref from usePagination
|
|
125
|
+
{
|
|
126
|
+
header: '#',
|
|
127
|
+
enableSorting: false
|
|
128
|
+
}
|
|
129
|
+
)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## 🔗 TypeScript Types
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
// Laravel Pagination Response
|
|
136
|
+
type LaravelPaginationResponse<T = any> = {
|
|
137
|
+
data: T[]
|
|
138
|
+
links: {
|
|
139
|
+
first: string | null
|
|
140
|
+
last: string | null
|
|
141
|
+
next: string | null
|
|
142
|
+
prev: string | null
|
|
143
|
+
}[]
|
|
144
|
+
meta: {
|
|
145
|
+
current_page: number
|
|
146
|
+
from: number
|
|
147
|
+
last_page: number
|
|
148
|
+
links: Array<{
|
|
149
|
+
url: string | null
|
|
150
|
+
label: string
|
|
151
|
+
active: boolean
|
|
152
|
+
}>
|
|
153
|
+
path: string
|
|
154
|
+
per_page: number
|
|
155
|
+
to: number
|
|
156
|
+
total: number
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Pagination Filters
|
|
161
|
+
interface PaginationFilters {
|
|
162
|
+
page?: number
|
|
163
|
+
per_page?: number
|
|
164
|
+
search?: string
|
|
165
|
+
[key: string]: any // Custom filters
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Sort State
|
|
169
|
+
interface SortState {
|
|
170
|
+
column: string | null
|
|
171
|
+
direction: 'asc' | 'desc'
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## 🎯 Usage with UI Libraries
|
|
176
|
+
|
|
177
|
+
### With Custom Table Component
|
|
178
|
+
|
|
179
|
+
```vue
|
|
180
|
+
<template>
|
|
181
|
+
<div>
|
|
182
|
+
<!-- Search -->
|
|
183
|
+
<input v-model="search" @input="handleSearchChange" />
|
|
184
|
+
|
|
185
|
+
<!-- Table -->
|
|
186
|
+
<table>
|
|
187
|
+
<thead>
|
|
188
|
+
<tr>
|
|
189
|
+
<th @click="handleSortChange('name')">Name</th>
|
|
190
|
+
<th @click="handleSortChange('email')">Email</th>
|
|
191
|
+
</tr>
|
|
192
|
+
</thead>
|
|
193
|
+
<tbody>
|
|
194
|
+
<tr v-for="user in tableData" :key="user.id">
|
|
195
|
+
<td>{{ user.name }}</td>
|
|
196
|
+
<td>{{ user.email }}</td>
|
|
197
|
+
</tr>
|
|
198
|
+
</tbody>
|
|
199
|
+
</table>
|
|
200
|
+
|
|
201
|
+
<!-- Pagination -->
|
|
202
|
+
<button
|
|
203
|
+
:disabled="pagination?.meta.current_page === 1"
|
|
204
|
+
@click="handlePageChange(pagination.meta.current_page - 1)"
|
|
205
|
+
>
|
|
206
|
+
Previous
|
|
207
|
+
</button>
|
|
208
|
+
<span>Page {{ pagination?.meta.current_page }} of {{ pagination?.meta.last_page }}</span>
|
|
209
|
+
<button
|
|
210
|
+
:disabled="pagination?.meta.current_page === pagination?.meta.last_page"
|
|
211
|
+
@click="handlePageChange(pagination.meta.current_page + 1)"
|
|
212
|
+
>
|
|
213
|
+
Next
|
|
214
|
+
</button>
|
|
215
|
+
</div>
|
|
216
|
+
</template>
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### With TanStack Table
|
|
220
|
+
|
|
221
|
+
```vue
|
|
222
|
+
<script setup lang="ts">
|
|
223
|
+
import { usePagination } from '@toniel/laravel-tanstack-pagination'
|
|
224
|
+
import { createColumnHelper, FlexRender, getCoreRowModel, useVueTable } from '@tanstack/vue-table'
|
|
225
|
+
|
|
226
|
+
const columnHelper = createColumnHelper<User>()
|
|
227
|
+
|
|
228
|
+
const {
|
|
229
|
+
tableData,
|
|
230
|
+
pagination,
|
|
231
|
+
perPage,
|
|
232
|
+
getNumberingColumn,
|
|
233
|
+
// ... other returns
|
|
234
|
+
} = usePagination(fetchUsers, { queryKey: 'users' })
|
|
235
|
+
|
|
236
|
+
const columns = [
|
|
237
|
+
getNumberingColumn({ header: '#' }),
|
|
238
|
+
columnHelper.accessor('name', { header: 'Name' }),
|
|
239
|
+
columnHelper.accessor('email', { header: 'Email' }),
|
|
240
|
+
]
|
|
241
|
+
|
|
242
|
+
const table = useVueTable({
|
|
243
|
+
get data() { return tableData.value },
|
|
244
|
+
columns,
|
|
245
|
+
getCoreRowModel: getCoreRowModel(),
|
|
246
|
+
})
|
|
247
|
+
</script>
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### With Shadcn-vue or Radix-vue
|
|
251
|
+
|
|
252
|
+
For ready-to-use DataTable component with shadcn-vue styling, use:
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
npm install @toniel/laravel-tanstack-datatable
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
See: https://www.npmjs.com/package/@toniel/laravel-tanstack-datatable
|
|
259
|
+
|
|
260
|
+
## 🔧 Laravel Backend Setup
|
|
261
|
+
|
|
262
|
+
Your Laravel API should return paginated responses in this format:
|
|
263
|
+
|
|
264
|
+
```php
|
|
265
|
+
// UserController.php
|
|
266
|
+
public function index(Request $request)
|
|
267
|
+
{
|
|
268
|
+
$query = User::query();
|
|
269
|
+
|
|
270
|
+
// Search
|
|
271
|
+
if ($request->has('search')) {
|
|
272
|
+
$query->where('name', 'like', "%{$request->search}%")
|
|
273
|
+
->orWhere('email', 'like', "%{$request->search}%");
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Sorting (format: sort[column]=direction)
|
|
277
|
+
foreach ($request->all() as $key => $value) {
|
|
278
|
+
if (str_starts_with($key, 'sort[')) {
|
|
279
|
+
preg_match('/sort\[(.*?)\]/', $key, $matches);
|
|
280
|
+
$column = $matches[1] ?? null;
|
|
281
|
+
if ($column) {
|
|
282
|
+
$query->orderBy($column, $value);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Paginate
|
|
288
|
+
$perPage = $request->input('per_page', 10);
|
|
289
|
+
return $query->paginate($perPage);
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
The response will automatically be in the correct format:
|
|
294
|
+
```json
|
|
295
|
+
{
|
|
296
|
+
"data": [...],
|
|
297
|
+
"links": {...},
|
|
298
|
+
"meta": {
|
|
299
|
+
"current_page": 1,
|
|
300
|
+
"from": 1,
|
|
301
|
+
"to": 10,
|
|
302
|
+
"total": 100,
|
|
303
|
+
"per_page": 10,
|
|
304
|
+
"last_page": 10
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## 🔗 Related Packages
|
|
310
|
+
|
|
311
|
+
- [`@toniel/laravel-tanstack-datatable`](https://github.com/toniel/laravel-tanstack-datatable) - Pre-built DataTable components
|
|
312
|
+
- [`@tanstack/vue-query`](https://tanstack.com/query/latest/docs/vue/overview) - Data fetching & caching library
|
|
313
|
+
- [`@tanstack/vue-table`](https://tanstack.com/table/latest/docs/framework/vue/vue-table) - Headless table library
|
|
314
|
+
|
|
315
|
+
## 🌟 Show Your Support
|
|
316
|
+
|
|
317
|
+
If this package helped you, please consider:
|
|
318
|
+
- ⭐ Starring the [GitHub repository](https://github.com/toniel/laravel-tanstack-pagination)
|
|
319
|
+
- 🐛 [Reporting bugs](https://github.com/toniel/laravel-tanstack-pagination/issues)
|
|
320
|
+
- 💡 [Suggesting new features](https://github.com/toniel/laravel-tanstack-pagination/issues)
|
|
321
|
+
- 🔧 [Contributing code](https://github.com/toniel/laravel-tanstack-pagination/pulls)
|
|
322
|
+
|
|
323
|
+
## 📄 License
|
|
324
|
+
|
|
325
|
+
[MIT](https://github.com/toniel/laravel-tanstack-pagination/blob/main/LICENSE) © [Toniel](https://github.com/toniel)
|
|
326
|
+
|
|
327
|
+
## 🤝 Contributing
|
|
328
|
+
|
|
329
|
+
Contributions, issues and feature requests are welcome!
|
|
330
|
+
|
|
331
|
+
1. Fork the repository
|
|
332
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
333
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
334
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
335
|
+
5. Open a Pull Request
|
|
336
|
+
|
|
337
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for more details.
|
|
338
|
+
|
|
339
|
+
## 📮 Contact
|
|
340
|
+
|
|
341
|
+
- GitHub: [@toniel](https://github.com/toniel)
|
|
342
|
+
- NPM: [@toniel](https://www.npmjs.com/~toniel)
|
|
343
|
+
|
|
344
|
+
## 🙏 Acknowledgments
|
|
345
|
+
|
|
346
|
+
Built with these amazing libraries:
|
|
347
|
+
- [Vue 3](https://vuejs.org/)
|
|
348
|
+
- [TanStack Query](https://tanstack.com/query/latest)
|
|
349
|
+
- [Laravel](https://laravel.com/)
|
|
350
|
+
|
|
351
|
+
---
|
|
70
352
|
|
|
71
|
-
|
|
353
|
+
<div align="center">
|
|
354
|
+
Made with ❤️ by <a href="https://github.com/toniel">Toniel</a>
|
|
355
|
+
</div>
|
|
72
356
|
|
|
73
|
-
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toniel/laravel-tanstack-pagination",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Vue 3 composables for Laravel pagination with TanStack Query",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -26,10 +26,22 @@
|
|
|
26
26
|
"laravel",
|
|
27
27
|
"pagination",
|
|
28
28
|
"composable",
|
|
29
|
-
"tanstack-query"
|
|
29
|
+
"tanstack-query",
|
|
30
|
+
"headless",
|
|
31
|
+
"typescript",
|
|
32
|
+
"vue-composables",
|
|
33
|
+
"laravel-api"
|
|
30
34
|
],
|
|
31
|
-
"author": "
|
|
35
|
+
"author": "Toniel <toniel@example.com>",
|
|
32
36
|
"license": "MIT",
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/toniel/laravel-tanstack-pagination.git"
|
|
40
|
+
},
|
|
41
|
+
"homepage": "https://github.com/toniel/laravel-tanstack-pagination#readme",
|
|
42
|
+
"bugs": {
|
|
43
|
+
"url": "https://github.com/toniel/laravel-tanstack-pagination/issues"
|
|
44
|
+
},
|
|
33
45
|
"peerDependencies": {
|
|
34
46
|
"vue": "^3.0.0",
|
|
35
47
|
"@tanstack/vue-query": "^5.0.0"
|