@toniel/laravel-tanstack-pagination 0.1.0 → 0.1.2
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 +468 -31
- package/dist/index.d.mts +12 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +12 -3
- package/dist/index.mjs +12 -3
- 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
|
|
9
22
|
```
|
|
10
23
|
|
|
11
|
-
|
|
24
|
+
### Peer Dependencies
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install vue @tanstack/vue-query
|
|
28
|
+
```
|
|
29
|
+
|
|
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,456 @@ 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 (including custom filters) |
|
|
98
|
+
| `customFilters` | `Ref<Record<string, any>>` | Custom filter state (for external use) |
|
|
99
|
+
| `isLoading` | `Ref<boolean>` | Loading state from TanStack Query |
|
|
100
|
+
| `error` | `Ref<Error \| null>` | Error state from TanStack Query |
|
|
101
|
+
| `handlePageChange` | `(page: number) => void` | Change page handler |
|
|
102
|
+
| `handlePerPageChange` | `(perPage: number) => void` | Change per page handler |
|
|
103
|
+
| `handleSearchChange` | `(search: string) => void` | Search change handler (debounced) |
|
|
104
|
+
| `handleSortChange` | `(column: string) => void` | Toggle sort on column |
|
|
105
|
+
| `handleFilterChange` | `(filters: Record<string, any>) => void` | Bulk update custom filters |
|
|
106
|
+
| `setFilter` | `(key: string, value: any) => void` | Add custom filter |
|
|
107
|
+
| `removeFilter` | `(key: string) => void` | Remove custom filter |
|
|
108
|
+
| `resetFilters` | `() => void` | Reset all filters to defaults |
|
|
109
|
+
| `getNumberingColumn` | `(options?) => ColumnDef` | Get numbering column for TanStack Table |
|
|
110
|
+
| `refetch` | TanStack Query refetch function |
|
|
111
|
+
| `...queryResult` | All other TanStack Query return values |
|
|
61
112
|
|
|
62
|
-
|
|
113
|
+
### `useTableNumbering()`
|
|
63
114
|
|
|
64
|
-
|
|
65
|
-
- `currentPage`: Current page number
|
|
66
|
-
- `perPage`: Items per page
|
|
115
|
+
Helper composable for creating table row numbering columns.
|
|
67
116
|
|
|
68
117
|
**Returns:**
|
|
69
|
-
- `
|
|
118
|
+
- `createNumberingColumn(pagination, perPage, options?)`: Function to create a numbering column definition for TanStack Table
|
|
119
|
+
|
|
120
|
+
**Example:**
|
|
121
|
+
```ts
|
|
122
|
+
const { createNumberingColumn } = useTableNumbering()
|
|
123
|
+
|
|
124
|
+
const numberingColumn = createNumberingColumn(
|
|
125
|
+
pagination, // ref from usePagination
|
|
126
|
+
perPage, // ref from usePagination
|
|
127
|
+
{
|
|
128
|
+
header: '#',
|
|
129
|
+
enableSorting: false
|
|
130
|
+
}
|
|
131
|
+
)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## 🔗 TypeScript Types
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
// Laravel Pagination Response
|
|
138
|
+
type LaravelPaginationResponse<T = any> = {
|
|
139
|
+
data: T[]
|
|
140
|
+
links: {
|
|
141
|
+
first: string | null
|
|
142
|
+
last: string | null
|
|
143
|
+
next: string | null
|
|
144
|
+
prev: string | null
|
|
145
|
+
}[]
|
|
146
|
+
meta: {
|
|
147
|
+
current_page: number
|
|
148
|
+
from: number
|
|
149
|
+
last_page: number
|
|
150
|
+
links: Array<{
|
|
151
|
+
url: string | null
|
|
152
|
+
label: string
|
|
153
|
+
active: boolean
|
|
154
|
+
}>
|
|
155
|
+
path: string
|
|
156
|
+
per_page: number
|
|
157
|
+
to: number
|
|
158
|
+
total: number
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Pagination Filters
|
|
163
|
+
interface PaginationFilters {
|
|
164
|
+
page?: number
|
|
165
|
+
per_page?: number
|
|
166
|
+
search?: string
|
|
167
|
+
[key: string]: any // Custom filters
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Sort State
|
|
171
|
+
interface SortState {
|
|
172
|
+
column: string | null
|
|
173
|
+
direction: 'asc' | 'desc'
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## 🎯 Usage with UI Libraries
|
|
178
|
+
|
|
179
|
+
### With Custom Table Component
|
|
180
|
+
|
|
181
|
+
```vue
|
|
182
|
+
<template>
|
|
183
|
+
<div>
|
|
184
|
+
<!-- Search -->
|
|
185
|
+
<input v-model="search" @input="handleSearchChange" />
|
|
186
|
+
|
|
187
|
+
<!-- Table -->
|
|
188
|
+
<table>
|
|
189
|
+
<thead>
|
|
190
|
+
<tr>
|
|
191
|
+
<th @click="handleSortChange('name')">Name</th>
|
|
192
|
+
<th @click="handleSortChange('email')">Email</th>
|
|
193
|
+
</tr>
|
|
194
|
+
</thead>
|
|
195
|
+
<tbody>
|
|
196
|
+
<tr v-for="user in tableData" :key="user.id">
|
|
197
|
+
<td>{{ user.name }}</td>
|
|
198
|
+
<td>{{ user.email }}</td>
|
|
199
|
+
</tr>
|
|
200
|
+
</tbody>
|
|
201
|
+
</table>
|
|
202
|
+
|
|
203
|
+
<!-- Pagination -->
|
|
204
|
+
<button
|
|
205
|
+
:disabled="pagination?.meta.current_page === 1"
|
|
206
|
+
@click="handlePageChange(pagination.meta.current_page - 1)"
|
|
207
|
+
>
|
|
208
|
+
Previous
|
|
209
|
+
</button>
|
|
210
|
+
<span>Page {{ pagination?.meta.current_page }} of {{ pagination?.meta.last_page }}</span>
|
|
211
|
+
<button
|
|
212
|
+
:disabled="pagination?.meta.current_page === pagination?.meta.last_page"
|
|
213
|
+
@click="handlePageChange(pagination.meta.current_page + 1)"
|
|
214
|
+
>
|
|
215
|
+
Next
|
|
216
|
+
</button>
|
|
217
|
+
</div>
|
|
218
|
+
</template>
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### With TanStack Table
|
|
222
|
+
|
|
223
|
+
```vue
|
|
224
|
+
<script setup lang="ts">
|
|
225
|
+
import { usePagination } from '@toniel/laravel-tanstack-pagination'
|
|
226
|
+
import { createColumnHelper, FlexRender, getCoreRowModel, useVueTable } from '@tanstack/vue-table'
|
|
227
|
+
|
|
228
|
+
const columnHelper = createColumnHelper<User>()
|
|
229
|
+
|
|
230
|
+
const {
|
|
231
|
+
tableData,
|
|
232
|
+
pagination,
|
|
233
|
+
perPage,
|
|
234
|
+
getNumberingColumn,
|
|
235
|
+
// ... other returns
|
|
236
|
+
} = usePagination(fetchUsers, { queryKey: 'users' })
|
|
237
|
+
|
|
238
|
+
const columns = [
|
|
239
|
+
getNumberingColumn({ header: '#' }),
|
|
240
|
+
columnHelper.accessor('name', { header: 'Name' }),
|
|
241
|
+
columnHelper.accessor('email', { header: 'Email' }),
|
|
242
|
+
]
|
|
243
|
+
|
|
244
|
+
const table = useVueTable({
|
|
245
|
+
get data() { return tableData.value },
|
|
246
|
+
columns,
|
|
247
|
+
getCoreRowModel: getCoreRowModel(),
|
|
248
|
+
})
|
|
249
|
+
</script>
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### With Shadcn-vue or Radix-vue
|
|
253
|
+
|
|
254
|
+
For ready-to-use DataTable component with shadcn-vue styling, use:
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
npm install @toniel/laravel-tanstack-datatable
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
See: https://www.npmjs.com/package/@toniel/laravel-tanstack-datatable
|
|
261
|
+
|
|
262
|
+
## 🔍 Filtering
|
|
263
|
+
|
|
264
|
+
The `usePagination` composable provides comprehensive filter management with proper state persistence across page changes.
|
|
265
|
+
|
|
266
|
+
### Single Filter Operations
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
const {
|
|
270
|
+
setFilter,
|
|
271
|
+
removeFilter,
|
|
272
|
+
customFilters,
|
|
273
|
+
refetch,
|
|
274
|
+
} = usePagination(fetchFn, { queryKey: 'users' })
|
|
275
|
+
|
|
276
|
+
// Set a single filter
|
|
277
|
+
setFilter('status', 'active')
|
|
278
|
+
setFilter('category', 'A')
|
|
279
|
+
|
|
280
|
+
// Remove a filter
|
|
281
|
+
removeFilter('status')
|
|
282
|
+
|
|
283
|
+
// The query will automatically refetch when filters change
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Bulk Filter Operations
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
const {
|
|
290
|
+
handleFilterChange,
|
|
291
|
+
customFilters,
|
|
292
|
+
refetch,
|
|
293
|
+
} = usePagination(fetchFn, { queryKey: 'users' })
|
|
294
|
+
|
|
295
|
+
// Bulk update multiple filters at once
|
|
296
|
+
handleFilterChange({
|
|
297
|
+
status: 'active',
|
|
298
|
+
category: 'A',
|
|
299
|
+
year: '2024'
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
// Or pass partial updates (will merge with existing)
|
|
303
|
+
handleFilterChange({
|
|
304
|
+
...customFilters.value,
|
|
305
|
+
status: 'inactive'
|
|
306
|
+
})
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Filter State Persistence
|
|
310
|
+
|
|
311
|
+
Custom filters are properly included in the TanStack Query cache key, ensuring:
|
|
312
|
+
- Filters persist when changing pages
|
|
313
|
+
- Filters persist when changing per page
|
|
314
|
+
- Correct cache invalidation on filter changes
|
|
315
|
+
- Back/forward navigation works correctly
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
// Filters are automatically included in queryKey
|
|
319
|
+
const { filters } = usePagination(fetchFn, { queryKey: 'users' })
|
|
320
|
+
|
|
321
|
+
// filters.value = { page: 1, per_page: 10, search: '', status: 'active', category: 'A' }
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Reset Filters
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
const {
|
|
328
|
+
resetFilters,
|
|
329
|
+
customFilters,
|
|
330
|
+
search,
|
|
331
|
+
perPage,
|
|
332
|
+
} = usePagination(fetchFn, { queryKey: 'users', defaultPerPage: 20 })
|
|
333
|
+
|
|
334
|
+
// Reset all filters to defaults
|
|
335
|
+
resetFilters()
|
|
336
|
+
|
|
337
|
+
// After reset:
|
|
338
|
+
// - customFilters = {}
|
|
339
|
+
// - search = ''
|
|
340
|
+
// - perPage = 20
|
|
341
|
+
// - page = 1
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Example: Complex Filter Form
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
<script setup lang="ts">
|
|
348
|
+
import { ref, computed } from 'vue'
|
|
349
|
+
import { usePagination } from '@toniel/laravel-tanstack-pagination'
|
|
350
|
+
|
|
351
|
+
// Filter form state (separate from composable)
|
|
352
|
+
const filterForm = ref({
|
|
353
|
+
status: '',
|
|
354
|
+
category: '',
|
|
355
|
+
year: new Date().getFullYear().toString(),
|
|
356
|
+
month: '',
|
|
357
|
+
})
|
|
358
|
+
|
|
359
|
+
const {
|
|
360
|
+
tableData,
|
|
361
|
+
pagination,
|
|
362
|
+
customFilters,
|
|
363
|
+
setFilter,
|
|
364
|
+
removeFilter,
|
|
365
|
+
handlePageChange,
|
|
366
|
+
refetch,
|
|
367
|
+
} = usePagination(
|
|
368
|
+
(filters) => axios.get('/api/transactions', { params: filters }),
|
|
369
|
+
{ queryKey: 'transactions', defaultPerPage: 20 }
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
// Apply filters
|
|
373
|
+
const applyFilters = () => {
|
|
374
|
+
// Clear existing custom filters first
|
|
375
|
+
if (filterForm.value.status) {
|
|
376
|
+
setFilter('status', filterForm.value.status)
|
|
377
|
+
} else {
|
|
378
|
+
removeFilter('status')
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
if (filterForm.value.category) {
|
|
382
|
+
setFilter('category', filterForm.value.category)
|
|
383
|
+
} else {
|
|
384
|
+
removeFilter('category')
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
if (filterForm.value.year) {
|
|
388
|
+
setFilter('year', filterForm.value.year)
|
|
389
|
+
} else {
|
|
390
|
+
removeFilter('year')
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
if (filterForm.value.month) {
|
|
394
|
+
setFilter('month', filterForm.value.month)
|
|
395
|
+
} else {
|
|
396
|
+
removeFilter('month')
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
refetch()
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// Clear all filters
|
|
403
|
+
const clearFilters = () => {
|
|
404
|
+
filterForm.value = { status: '', category: '', year: new Date().getFullYear().toString(), month: '' }
|
|
405
|
+
removeFilter('status')
|
|
406
|
+
removeFilter('category')
|
|
407
|
+
removeFilter('year')
|
|
408
|
+
removeFilter('month')
|
|
409
|
+
refetch()
|
|
410
|
+
}
|
|
411
|
+
</script>
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
## 🔧 Laravel Backend Setup
|
|
415
|
+
|
|
416
|
+
Your Laravel API should return paginated responses in this format:
|
|
417
|
+
|
|
418
|
+
```php
|
|
419
|
+
// UserController.php
|
|
420
|
+
public function index(Request $request)
|
|
421
|
+
{
|
|
422
|
+
$query = User::query();
|
|
423
|
+
|
|
424
|
+
// Search
|
|
425
|
+
if ($request->has('search')) {
|
|
426
|
+
$query->where('name', 'like', "%{$request->search}%")
|
|
427
|
+
->orWhere('email', 'like', "%{$request->search}%");
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Sorting (format: sort[column]=direction)
|
|
431
|
+
foreach ($request->all() as $key => $value) {
|
|
432
|
+
if (str_starts_with($key, 'sort[')) {
|
|
433
|
+
preg_match('/sort\[(.*?)\]/', $key, $matches);
|
|
434
|
+
$column = $matches[1] ?? null;
|
|
435
|
+
if ($column) {
|
|
436
|
+
$query->orderBy($column, $value);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// Paginate
|
|
442
|
+
$perPage = $request->input('per_page', 10);
|
|
443
|
+
return $query->paginate($perPage);
|
|
444
|
+
}
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
The response will automatically be in the correct format:
|
|
448
|
+
```json
|
|
449
|
+
{
|
|
450
|
+
"data": [...],
|
|
451
|
+
"links": {...},
|
|
452
|
+
"meta": {
|
|
453
|
+
"current_page": 1,
|
|
454
|
+
"from": 1,
|
|
455
|
+
"to": 10,
|
|
456
|
+
"total": 100,
|
|
457
|
+
"per_page": 10,
|
|
458
|
+
"last_page": 10
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
## 🔗 Related Packages
|
|
464
|
+
|
|
465
|
+
- [`@toniel/laravel-tanstack-datatable`](https://github.com/toniel/laravel-tanstack-datatable) - Pre-built DataTable components
|
|
466
|
+
- [`@tanstack/vue-query`](https://tanstack.com/query/latest/docs/vue/overview) - Data fetching & caching library
|
|
467
|
+
- [`@tanstack/vue-table`](https://tanstack.com/table/latest/docs/framework/vue/vue-table) - Headless table library
|
|
468
|
+
|
|
469
|
+
## 🌟 Show Your Support
|
|
470
|
+
|
|
471
|
+
If this package helped you, please consider:
|
|
472
|
+
- ⭐ Starring the [GitHub repository](https://github.com/toniel/laravel-tanstack-pagination)
|
|
473
|
+
- 🐛 [Reporting bugs](https://github.com/toniel/laravel-tanstack-pagination/issues)
|
|
474
|
+
- 💡 [Suggesting new features](https://github.com/toniel/laravel-tanstack-pagination/issues)
|
|
475
|
+
- 🔧 [Contributing code](https://github.com/toniel/laravel-tanstack-pagination/pulls)
|
|
476
|
+
|
|
477
|
+
## 📄 License
|
|
478
|
+
|
|
479
|
+
[MIT](https://github.com/toniel/laravel-tanstack-pagination/blob/main/LICENSE) © [Toniel](https://github.com/toniel)
|
|
480
|
+
|
|
481
|
+
## 🤝 Contributing
|
|
482
|
+
|
|
483
|
+
Contributions, issues and feature requests are welcome!
|
|
484
|
+
|
|
485
|
+
1. Fork the repository
|
|
486
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
487
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
488
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
489
|
+
5. Open a Pull Request
|
|
490
|
+
|
|
491
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for more details.
|
|
492
|
+
|
|
493
|
+
## 📮 Contact
|
|
494
|
+
|
|
495
|
+
- GitHub: [@toniel](https://github.com/toniel)
|
|
496
|
+
- NPM: [@toniel](https://www.npmjs.com/~toniel)
|
|
497
|
+
|
|
498
|
+
## 🙏 Acknowledgments
|
|
499
|
+
|
|
500
|
+
Built with these amazing libraries:
|
|
501
|
+
- [Vue 3](https://vuejs.org/)
|
|
502
|
+
- [TanStack Query](https://tanstack.com/query/latest)
|
|
503
|
+
- [Laravel](https://laravel.com/)
|
|
504
|
+
|
|
505
|
+
---
|
|
70
506
|
|
|
71
|
-
|
|
507
|
+
<div align="center">
|
|
508
|
+
Made with ❤️ by <a href="https://github.com/toniel">Toniel</a>
|
|
509
|
+
</div>
|
|
72
510
|
|
|
73
|
-
MIT
|
package/dist/index.d.mts
CHANGED
|
@@ -52,6 +52,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
52
52
|
handlePerPageChange: (newPerPage: number) => void;
|
|
53
53
|
handleSearchChange: (newSearch: string) => void;
|
|
54
54
|
handleSortChange: (column: string) => void;
|
|
55
|
+
handleFilterChange: (newFilters: Record<string, any>) => void;
|
|
55
56
|
resetFilters: () => void;
|
|
56
57
|
setFilter: (key: string, value: any) => void;
|
|
57
58
|
removeFilter: (key: string) => void;
|
|
@@ -101,6 +102,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
101
102
|
sortBy: vue.Ref<string | null, string | null>;
|
|
102
103
|
sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
|
|
103
104
|
filters: vue.ComputedRef<PaginationFilters>;
|
|
105
|
+
customFilters: vue.Ref<Record<string, any>, Record<string, any>>;
|
|
104
106
|
} | {
|
|
105
107
|
tableData: vue.ComputedRef<T[]>;
|
|
106
108
|
pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
|
|
@@ -108,6 +110,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
108
110
|
handlePerPageChange: (newPerPage: number) => void;
|
|
109
111
|
handleSearchChange: (newSearch: string) => void;
|
|
110
112
|
handleSortChange: (column: string) => void;
|
|
113
|
+
handleFilterChange: (newFilters: Record<string, any>) => void;
|
|
111
114
|
resetFilters: () => void;
|
|
112
115
|
setFilter: (key: string, value: any) => void;
|
|
113
116
|
removeFilter: (key: string) => void;
|
|
@@ -157,6 +160,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
157
160
|
sortBy: vue.Ref<string | null, string | null>;
|
|
158
161
|
sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
|
|
159
162
|
filters: vue.ComputedRef<PaginationFilters>;
|
|
163
|
+
customFilters: vue.Ref<Record<string, any>, Record<string, any>>;
|
|
160
164
|
} | {
|
|
161
165
|
tableData: vue.ComputedRef<T[]>;
|
|
162
166
|
pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
|
|
@@ -164,6 +168,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
164
168
|
handlePerPageChange: (newPerPage: number) => void;
|
|
165
169
|
handleSearchChange: (newSearch: string) => void;
|
|
166
170
|
handleSortChange: (column: string) => void;
|
|
171
|
+
handleFilterChange: (newFilters: Record<string, any>) => void;
|
|
167
172
|
resetFilters: () => void;
|
|
168
173
|
setFilter: (key: string, value: any) => void;
|
|
169
174
|
removeFilter: (key: string) => void;
|
|
@@ -213,6 +218,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
213
218
|
sortBy: vue.Ref<string | null, string | null>;
|
|
214
219
|
sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
|
|
215
220
|
filters: vue.ComputedRef<PaginationFilters>;
|
|
221
|
+
customFilters: vue.Ref<Record<string, any>, Record<string, any>>;
|
|
216
222
|
} | {
|
|
217
223
|
tableData: vue.ComputedRef<T[]>;
|
|
218
224
|
pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
|
|
@@ -220,6 +226,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
220
226
|
handlePerPageChange: (newPerPage: number) => void;
|
|
221
227
|
handleSearchChange: (newSearch: string) => void;
|
|
222
228
|
handleSortChange: (column: string) => void;
|
|
229
|
+
handleFilterChange: (newFilters: Record<string, any>) => void;
|
|
223
230
|
resetFilters: () => void;
|
|
224
231
|
setFilter: (key: string, value: any) => void;
|
|
225
232
|
removeFilter: (key: string) => void;
|
|
@@ -269,6 +276,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
269
276
|
sortBy: vue.Ref<string | null, string | null>;
|
|
270
277
|
sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
|
|
271
278
|
filters: vue.ComputedRef<PaginationFilters>;
|
|
279
|
+
customFilters: vue.Ref<Record<string, any>, Record<string, any>>;
|
|
272
280
|
} | {
|
|
273
281
|
tableData: vue.ComputedRef<T[]>;
|
|
274
282
|
pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
|
|
@@ -276,6 +284,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
276
284
|
handlePerPageChange: (newPerPage: number) => void;
|
|
277
285
|
handleSearchChange: (newSearch: string) => void;
|
|
278
286
|
handleSortChange: (column: string) => void;
|
|
287
|
+
handleFilterChange: (newFilters: Record<string, any>) => void;
|
|
279
288
|
resetFilters: () => void;
|
|
280
289
|
setFilter: (key: string, value: any) => void;
|
|
281
290
|
removeFilter: (key: string) => void;
|
|
@@ -325,6 +334,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
325
334
|
sortBy: vue.Ref<string | null, string | null>;
|
|
326
335
|
sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
|
|
327
336
|
filters: vue.ComputedRef<PaginationFilters>;
|
|
337
|
+
customFilters: vue.Ref<Record<string, any>, Record<string, any>>;
|
|
328
338
|
} | {
|
|
329
339
|
tableData: vue.ComputedRef<T[]>;
|
|
330
340
|
pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
|
|
@@ -332,6 +342,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
332
342
|
handlePerPageChange: (newPerPage: number) => void;
|
|
333
343
|
handleSearchChange: (newSearch: string) => void;
|
|
334
344
|
handleSortChange: (column: string) => void;
|
|
345
|
+
handleFilterChange: (newFilters: Record<string, any>) => void;
|
|
335
346
|
resetFilters: () => void;
|
|
336
347
|
setFilter: (key: string, value: any) => void;
|
|
337
348
|
removeFilter: (key: string) => void;
|
|
@@ -381,6 +392,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
381
392
|
sortBy: vue.Ref<string | null, string | null>;
|
|
382
393
|
sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
|
|
383
394
|
filters: vue.ComputedRef<PaginationFilters>;
|
|
395
|
+
customFilters: vue.Ref<Record<string, any>, Record<string, any>>;
|
|
384
396
|
};
|
|
385
397
|
|
|
386
398
|
interface NumberingOptions {
|
package/dist/index.d.ts
CHANGED
|
@@ -52,6 +52,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
52
52
|
handlePerPageChange: (newPerPage: number) => void;
|
|
53
53
|
handleSearchChange: (newSearch: string) => void;
|
|
54
54
|
handleSortChange: (column: string) => void;
|
|
55
|
+
handleFilterChange: (newFilters: Record<string, any>) => void;
|
|
55
56
|
resetFilters: () => void;
|
|
56
57
|
setFilter: (key: string, value: any) => void;
|
|
57
58
|
removeFilter: (key: string) => void;
|
|
@@ -101,6 +102,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
101
102
|
sortBy: vue.Ref<string | null, string | null>;
|
|
102
103
|
sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
|
|
103
104
|
filters: vue.ComputedRef<PaginationFilters>;
|
|
105
|
+
customFilters: vue.Ref<Record<string, any>, Record<string, any>>;
|
|
104
106
|
} | {
|
|
105
107
|
tableData: vue.ComputedRef<T[]>;
|
|
106
108
|
pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
|
|
@@ -108,6 +110,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
108
110
|
handlePerPageChange: (newPerPage: number) => void;
|
|
109
111
|
handleSearchChange: (newSearch: string) => void;
|
|
110
112
|
handleSortChange: (column: string) => void;
|
|
113
|
+
handleFilterChange: (newFilters: Record<string, any>) => void;
|
|
111
114
|
resetFilters: () => void;
|
|
112
115
|
setFilter: (key: string, value: any) => void;
|
|
113
116
|
removeFilter: (key: string) => void;
|
|
@@ -157,6 +160,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
157
160
|
sortBy: vue.Ref<string | null, string | null>;
|
|
158
161
|
sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
|
|
159
162
|
filters: vue.ComputedRef<PaginationFilters>;
|
|
163
|
+
customFilters: vue.Ref<Record<string, any>, Record<string, any>>;
|
|
160
164
|
} | {
|
|
161
165
|
tableData: vue.ComputedRef<T[]>;
|
|
162
166
|
pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
|
|
@@ -164,6 +168,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
164
168
|
handlePerPageChange: (newPerPage: number) => void;
|
|
165
169
|
handleSearchChange: (newSearch: string) => void;
|
|
166
170
|
handleSortChange: (column: string) => void;
|
|
171
|
+
handleFilterChange: (newFilters: Record<string, any>) => void;
|
|
167
172
|
resetFilters: () => void;
|
|
168
173
|
setFilter: (key: string, value: any) => void;
|
|
169
174
|
removeFilter: (key: string) => void;
|
|
@@ -213,6 +218,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
213
218
|
sortBy: vue.Ref<string | null, string | null>;
|
|
214
219
|
sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
|
|
215
220
|
filters: vue.ComputedRef<PaginationFilters>;
|
|
221
|
+
customFilters: vue.Ref<Record<string, any>, Record<string, any>>;
|
|
216
222
|
} | {
|
|
217
223
|
tableData: vue.ComputedRef<T[]>;
|
|
218
224
|
pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
|
|
@@ -220,6 +226,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
220
226
|
handlePerPageChange: (newPerPage: number) => void;
|
|
221
227
|
handleSearchChange: (newSearch: string) => void;
|
|
222
228
|
handleSortChange: (column: string) => void;
|
|
229
|
+
handleFilterChange: (newFilters: Record<string, any>) => void;
|
|
223
230
|
resetFilters: () => void;
|
|
224
231
|
setFilter: (key: string, value: any) => void;
|
|
225
232
|
removeFilter: (key: string) => void;
|
|
@@ -269,6 +276,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
269
276
|
sortBy: vue.Ref<string | null, string | null>;
|
|
270
277
|
sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
|
|
271
278
|
filters: vue.ComputedRef<PaginationFilters>;
|
|
279
|
+
customFilters: vue.Ref<Record<string, any>, Record<string, any>>;
|
|
272
280
|
} | {
|
|
273
281
|
tableData: vue.ComputedRef<T[]>;
|
|
274
282
|
pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
|
|
@@ -276,6 +284,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
276
284
|
handlePerPageChange: (newPerPage: number) => void;
|
|
277
285
|
handleSearchChange: (newSearch: string) => void;
|
|
278
286
|
handleSortChange: (column: string) => void;
|
|
287
|
+
handleFilterChange: (newFilters: Record<string, any>) => void;
|
|
279
288
|
resetFilters: () => void;
|
|
280
289
|
setFilter: (key: string, value: any) => void;
|
|
281
290
|
removeFilter: (key: string) => void;
|
|
@@ -325,6 +334,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
325
334
|
sortBy: vue.Ref<string | null, string | null>;
|
|
326
335
|
sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
|
|
327
336
|
filters: vue.ComputedRef<PaginationFilters>;
|
|
337
|
+
customFilters: vue.Ref<Record<string, any>, Record<string, any>>;
|
|
328
338
|
} | {
|
|
329
339
|
tableData: vue.ComputedRef<T[]>;
|
|
330
340
|
pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
|
|
@@ -332,6 +342,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
332
342
|
handlePerPageChange: (newPerPage: number) => void;
|
|
333
343
|
handleSearchChange: (newSearch: string) => void;
|
|
334
344
|
handleSortChange: (column: string) => void;
|
|
345
|
+
handleFilterChange: (newFilters: Record<string, any>) => void;
|
|
335
346
|
resetFilters: () => void;
|
|
336
347
|
setFilter: (key: string, value: any) => void;
|
|
337
348
|
removeFilter: (key: string) => void;
|
|
@@ -381,6 +392,7 @@ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) =>
|
|
|
381
392
|
sortBy: vue.Ref<string | null, string | null>;
|
|
382
393
|
sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
|
|
383
394
|
filters: vue.ComputedRef<PaginationFilters>;
|
|
395
|
+
customFilters: vue.Ref<Record<string, any>, Record<string, any>>;
|
|
384
396
|
};
|
|
385
397
|
|
|
386
398
|
interface NumberingOptions {
|
package/dist/index.js
CHANGED
|
@@ -103,11 +103,13 @@ function usePagination(fetchFn, options) {
|
|
|
103
103
|
const search = (0, import_vue2.ref)(options.defaultSearch || "");
|
|
104
104
|
const sortBy = (0, import_vue2.ref)(options.defaultSort?.column || null);
|
|
105
105
|
const sortDirection = (0, import_vue2.ref)(options.defaultSort?.direction || "asc");
|
|
106
|
+
const customFilters = (0, import_vue2.ref)({});
|
|
106
107
|
const filters = (0, import_vue2.computed)(() => {
|
|
107
108
|
const baseFilters = {
|
|
108
109
|
page: currentPage.value,
|
|
109
110
|
per_page: perPage.value,
|
|
110
|
-
search: search.value
|
|
111
|
+
search: search.value,
|
|
112
|
+
...customFilters.value
|
|
111
113
|
};
|
|
112
114
|
if (sortBy.value) {
|
|
113
115
|
baseFilters[`sort[${sortBy.value}]`] = sortDirection.value;
|
|
@@ -143,11 +145,15 @@ function usePagination(fetchFn, options) {
|
|
|
143
145
|
currentPage.value = 1;
|
|
144
146
|
};
|
|
145
147
|
const setFilter = (key, value) => {
|
|
146
|
-
|
|
148
|
+
customFilters.value[key] = value;
|
|
147
149
|
currentPage.value = 1;
|
|
148
150
|
};
|
|
149
151
|
const removeFilter = (key) => {
|
|
150
|
-
delete
|
|
152
|
+
delete customFilters.value[key];
|
|
153
|
+
currentPage.value = 1;
|
|
154
|
+
};
|
|
155
|
+
const handleFilterChange = (newFilters) => {
|
|
156
|
+
customFilters.value = { ...newFilters };
|
|
151
157
|
currentPage.value = 1;
|
|
152
158
|
};
|
|
153
159
|
const resetFilters = () => {
|
|
@@ -156,6 +162,7 @@ function usePagination(fetchFn, options) {
|
|
|
156
162
|
search.value = options.defaultSearch || "";
|
|
157
163
|
sortBy.value = options.defaultSort?.column || null;
|
|
158
164
|
sortDirection.value = options.defaultSort?.direction || "asc";
|
|
165
|
+
customFilters.value = {};
|
|
159
166
|
};
|
|
160
167
|
let searchTimeout;
|
|
161
168
|
(0, import_vue2.watch)(search, () => {
|
|
@@ -176,6 +183,7 @@ function usePagination(fetchFn, options) {
|
|
|
176
183
|
sortBy,
|
|
177
184
|
sortDirection,
|
|
178
185
|
filters,
|
|
186
|
+
customFilters,
|
|
179
187
|
// Query result
|
|
180
188
|
...queryResult,
|
|
181
189
|
// Computed
|
|
@@ -186,6 +194,7 @@ function usePagination(fetchFn, options) {
|
|
|
186
194
|
handlePerPageChange,
|
|
187
195
|
handleSearchChange,
|
|
188
196
|
handleSortChange,
|
|
197
|
+
handleFilterChange,
|
|
189
198
|
resetFilters,
|
|
190
199
|
setFilter,
|
|
191
200
|
removeFilter,
|
package/dist/index.mjs
CHANGED
|
@@ -76,11 +76,13 @@ function usePagination(fetchFn, options) {
|
|
|
76
76
|
const search = ref(options.defaultSearch || "");
|
|
77
77
|
const sortBy = ref(options.defaultSort?.column || null);
|
|
78
78
|
const sortDirection = ref(options.defaultSort?.direction || "asc");
|
|
79
|
+
const customFilters = ref({});
|
|
79
80
|
const filters = computed(() => {
|
|
80
81
|
const baseFilters = {
|
|
81
82
|
page: currentPage.value,
|
|
82
83
|
per_page: perPage.value,
|
|
83
|
-
search: search.value
|
|
84
|
+
search: search.value,
|
|
85
|
+
...customFilters.value
|
|
84
86
|
};
|
|
85
87
|
if (sortBy.value) {
|
|
86
88
|
baseFilters[`sort[${sortBy.value}]`] = sortDirection.value;
|
|
@@ -116,11 +118,15 @@ function usePagination(fetchFn, options) {
|
|
|
116
118
|
currentPage.value = 1;
|
|
117
119
|
};
|
|
118
120
|
const setFilter = (key, value) => {
|
|
119
|
-
|
|
121
|
+
customFilters.value[key] = value;
|
|
120
122
|
currentPage.value = 1;
|
|
121
123
|
};
|
|
122
124
|
const removeFilter = (key) => {
|
|
123
|
-
delete
|
|
125
|
+
delete customFilters.value[key];
|
|
126
|
+
currentPage.value = 1;
|
|
127
|
+
};
|
|
128
|
+
const handleFilterChange = (newFilters) => {
|
|
129
|
+
customFilters.value = { ...newFilters };
|
|
124
130
|
currentPage.value = 1;
|
|
125
131
|
};
|
|
126
132
|
const resetFilters = () => {
|
|
@@ -129,6 +135,7 @@ function usePagination(fetchFn, options) {
|
|
|
129
135
|
search.value = options.defaultSearch || "";
|
|
130
136
|
sortBy.value = options.defaultSort?.column || null;
|
|
131
137
|
sortDirection.value = options.defaultSort?.direction || "asc";
|
|
138
|
+
customFilters.value = {};
|
|
132
139
|
};
|
|
133
140
|
let searchTimeout;
|
|
134
141
|
watch(search, () => {
|
|
@@ -149,6 +156,7 @@ function usePagination(fetchFn, options) {
|
|
|
149
156
|
sortBy,
|
|
150
157
|
sortDirection,
|
|
151
158
|
filters,
|
|
159
|
+
customFilters,
|
|
152
160
|
// Query result
|
|
153
161
|
...queryResult,
|
|
154
162
|
// Computed
|
|
@@ -159,6 +167,7 @@ function usePagination(fetchFn, options) {
|
|
|
159
167
|
handlePerPageChange,
|
|
160
168
|
handleSearchChange,
|
|
161
169
|
handleSortChange,
|
|
170
|
+
handleFilterChange,
|
|
162
171
|
resetFilters,
|
|
163
172
|
setFilter,
|
|
164
173
|
removeFilter,
|
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.2",
|
|
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"
|