@toniel/laravel-tanstack-pagination 0.1.0

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/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # Laravel TanStack Pagination
2
+
3
+ Vue 3 composables untuk Laravel pagination dengan TanStack Query.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @toniel/laravel-tanstack-pagination
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { usePagination } from '@toniel/laravel-tanstack-pagination'
15
+
16
+ const {
17
+ tableData,
18
+ pagination,
19
+ handlePageChange,
20
+ handleSearchChange
21
+ } = usePagination(
22
+ (filters) => axios.get('/api/users', { params: filters }),
23
+ {
24
+ queryKey: 'users',
25
+ defaultPerPage: 10
26
+ }
27
+ )
28
+ ```
29
+
30
+ ## Features
31
+
32
+ - ✅ Laravel pagination support
33
+ - ✅ TanStack Query integration
34
+ - ✅ Search with debounce
35
+ - ✅ Sorting
36
+ - ✅ Table numbering helper
37
+ - ✅ TypeScript support
38
+
39
+ ## API
40
+
41
+ ### `usePagination(fetchFn, options)`
42
+
43
+ Main composable for handling Laravel pagination.
44
+
45
+ **Parameters:**
46
+ - `fetchFn`: Function that fetches data from Laravel API
47
+ - `options`: Configuration options
48
+ - `queryKey`: Unique key for the query
49
+ - `defaultPerPage`: Items per page (default: 10)
50
+
51
+ **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
+
60
+ ### `useTableNumbering(currentPage, perPage)`
61
+
62
+ Helper composable for table row numbering.
63
+
64
+ **Parameters:**
65
+ - `currentPage`: Current page number
66
+ - `perPage`: Items per page
67
+
68
+ **Returns:**
69
+ - `getRowNumber(index)`: Function to get row number for index
70
+
71
+ ## License
72
+
73
+ MIT
@@ -0,0 +1,414 @@
1
+ import * as _tanstack_vue_query from '@tanstack/vue-query';
2
+ import { UseQueryOptions } from '@tanstack/vue-query';
3
+ import * as vue from 'vue';
4
+ import { Ref, ComputedRef } from 'vue';
5
+
6
+ type LaravelPaginationResponse<T = any> = {
7
+ data: T[];
8
+ links: Array<{
9
+ first: string | null;
10
+ last: string | null;
11
+ next: string | null;
12
+ prev: string | null;
13
+ }>;
14
+ meta: {
15
+ current_page: number;
16
+ from: number;
17
+ last_page: number;
18
+ links: Array<{
19
+ url: string | null;
20
+ label: string;
21
+ active: boolean;
22
+ }>;
23
+ path: string;
24
+ per_page: number;
25
+ to: number;
26
+ total: number;
27
+ };
28
+ };
29
+ interface PaginationFilters {
30
+ page?: number;
31
+ per_page?: number;
32
+ search?: string;
33
+ sort_by?: string;
34
+ sort_direction?: 'asc' | 'desc';
35
+ [key: string]: any;
36
+ }
37
+ interface SortState {
38
+ column: string | null;
39
+ direction: 'asc' | 'desc';
40
+ }
41
+
42
+ interface UsePaginationOptions<T> extends Omit<UseQueryOptions<LaravelPaginationResponse<T>>, 'queryKey' | 'queryFn'> {
43
+ queryKey: string;
44
+ defaultPerPage?: number;
45
+ defaultSearch?: string;
46
+ defaultSort?: SortState;
47
+ }
48
+ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) => Promise<LaravelPaginationResponse<T>>, options: UsePaginationOptions<T>): {
49
+ tableData: vue.ComputedRef<T[]>;
50
+ pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
51
+ handlePageChange: (page: number) => void;
52
+ handlePerPageChange: (newPerPage: number) => void;
53
+ handleSearchChange: (newSearch: string) => void;
54
+ handleSortChange: (column: string) => void;
55
+ resetFilters: () => void;
56
+ setFilter: (key: string, value: any) => void;
57
+ removeFilter: (key: string) => void;
58
+ getNumberingColumn: (options?: any) => {
59
+ accessorKey: string;
60
+ header: string;
61
+ enableSorting: boolean;
62
+ meta: {
63
+ style: {
64
+ width: string;
65
+ };
66
+ };
67
+ cell: ({ row }: any) => vue.VNode<vue.RendererNode, vue.RendererElement, {
68
+ [key: string]: any;
69
+ }>;
70
+ };
71
+ data: vue.Ref<LaravelPaginationResponse<T>, LaravelPaginationResponse<T>>;
72
+ error: vue.Ref<Error, Error>;
73
+ isError: vue.Ref<true, true>;
74
+ isPending: vue.Ref<false, false>;
75
+ isLoading: vue.Ref<false, false>;
76
+ isLoadingError: vue.Ref<false, false>;
77
+ isRefetchError: vue.Ref<true, true>;
78
+ isSuccess: vue.Ref<false, false>;
79
+ isPlaceholderData: vue.Ref<false, false>;
80
+ status: vue.Ref<"error", "error">;
81
+ dataUpdatedAt: vue.Ref<number, number>;
82
+ errorUpdatedAt: vue.Ref<number, number>;
83
+ failureCount: vue.Ref<number, number>;
84
+ failureReason: vue.Ref<Error | null, Error | null>;
85
+ errorUpdateCount: vue.Ref<number, number>;
86
+ isFetched: vue.Ref<boolean, boolean>;
87
+ isFetchedAfterMount: vue.Ref<boolean, boolean>;
88
+ isFetching: vue.Ref<boolean, boolean>;
89
+ isInitialLoading: vue.Ref<boolean, boolean>;
90
+ isPaused: vue.Ref<boolean, boolean>;
91
+ isRefetching: vue.Ref<boolean, boolean>;
92
+ isStale: vue.Ref<boolean, boolean>;
93
+ isEnabled: vue.Ref<boolean, boolean>;
94
+ refetch: (options?: _tanstack_vue_query.RefetchOptions) => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
95
+ fetchStatus: vue.Ref<_tanstack_vue_query.FetchStatus, _tanstack_vue_query.FetchStatus>;
96
+ promise: vue.Ref<Promise<LaravelPaginationResponse<T>>, Promise<LaravelPaginationResponse<T>>>;
97
+ suspense: () => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
98
+ currentPage: vue.Ref<number, number>;
99
+ perPage: vue.Ref<number, number>;
100
+ search: vue.Ref<string, string>;
101
+ sortBy: vue.Ref<string | null, string | null>;
102
+ sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
103
+ filters: vue.ComputedRef<PaginationFilters>;
104
+ } | {
105
+ tableData: vue.ComputedRef<T[]>;
106
+ pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
107
+ handlePageChange: (page: number) => void;
108
+ handlePerPageChange: (newPerPage: number) => void;
109
+ handleSearchChange: (newSearch: string) => void;
110
+ handleSortChange: (column: string) => void;
111
+ resetFilters: () => void;
112
+ setFilter: (key: string, value: any) => void;
113
+ removeFilter: (key: string) => void;
114
+ getNumberingColumn: (options?: any) => {
115
+ accessorKey: string;
116
+ header: string;
117
+ enableSorting: boolean;
118
+ meta: {
119
+ style: {
120
+ width: string;
121
+ };
122
+ };
123
+ cell: ({ row }: any) => vue.VNode<vue.RendererNode, vue.RendererElement, {
124
+ [key: string]: any;
125
+ }>;
126
+ };
127
+ data: vue.Ref<LaravelPaginationResponse<T>, LaravelPaginationResponse<T>>;
128
+ error: vue.Ref<null, null>;
129
+ isError: vue.Ref<false, false>;
130
+ isPending: vue.Ref<false, false>;
131
+ isLoading: vue.Ref<false, false>;
132
+ isLoadingError: vue.Ref<false, false>;
133
+ isRefetchError: vue.Ref<false, false>;
134
+ isSuccess: vue.Ref<true, true>;
135
+ isPlaceholderData: vue.Ref<false, false>;
136
+ status: vue.Ref<"success", "success">;
137
+ dataUpdatedAt: vue.Ref<number, number>;
138
+ errorUpdatedAt: vue.Ref<number, number>;
139
+ failureCount: vue.Ref<number, number>;
140
+ failureReason: vue.Ref<Error | null, Error | null>;
141
+ errorUpdateCount: vue.Ref<number, number>;
142
+ isFetched: vue.Ref<boolean, boolean>;
143
+ isFetchedAfterMount: vue.Ref<boolean, boolean>;
144
+ isFetching: vue.Ref<boolean, boolean>;
145
+ isInitialLoading: vue.Ref<boolean, boolean>;
146
+ isPaused: vue.Ref<boolean, boolean>;
147
+ isRefetching: vue.Ref<boolean, boolean>;
148
+ isStale: vue.Ref<boolean, boolean>;
149
+ isEnabled: vue.Ref<boolean, boolean>;
150
+ refetch: (options?: _tanstack_vue_query.RefetchOptions) => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
151
+ fetchStatus: vue.Ref<_tanstack_vue_query.FetchStatus, _tanstack_vue_query.FetchStatus>;
152
+ promise: vue.Ref<Promise<LaravelPaginationResponse<T>>, Promise<LaravelPaginationResponse<T>>>;
153
+ suspense: () => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
154
+ currentPage: vue.Ref<number, number>;
155
+ perPage: vue.Ref<number, number>;
156
+ search: vue.Ref<string, string>;
157
+ sortBy: vue.Ref<string | null, string | null>;
158
+ sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
159
+ filters: vue.ComputedRef<PaginationFilters>;
160
+ } | {
161
+ tableData: vue.ComputedRef<T[]>;
162
+ pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
163
+ handlePageChange: (page: number) => void;
164
+ handlePerPageChange: (newPerPage: number) => void;
165
+ handleSearchChange: (newSearch: string) => void;
166
+ handleSortChange: (column: string) => void;
167
+ resetFilters: () => void;
168
+ setFilter: (key: string, value: any) => void;
169
+ removeFilter: (key: string) => void;
170
+ getNumberingColumn: (options?: any) => {
171
+ accessorKey: string;
172
+ header: string;
173
+ enableSorting: boolean;
174
+ meta: {
175
+ style: {
176
+ width: string;
177
+ };
178
+ };
179
+ cell: ({ row }: any) => vue.VNode<vue.RendererNode, vue.RendererElement, {
180
+ [key: string]: any;
181
+ }>;
182
+ };
183
+ data: vue.Ref<undefined, undefined>;
184
+ error: vue.Ref<Error, Error>;
185
+ isError: vue.Ref<true, true>;
186
+ isPending: vue.Ref<false, false>;
187
+ isLoading: vue.Ref<false, false>;
188
+ isLoadingError: vue.Ref<true, true>;
189
+ isRefetchError: vue.Ref<false, false>;
190
+ isSuccess: vue.Ref<false, false>;
191
+ isPlaceholderData: vue.Ref<false, false>;
192
+ status: vue.Ref<"error", "error">;
193
+ dataUpdatedAt: vue.Ref<number, number>;
194
+ errorUpdatedAt: vue.Ref<number, number>;
195
+ failureCount: vue.Ref<number, number>;
196
+ failureReason: vue.Ref<Error | null, Error | null>;
197
+ errorUpdateCount: vue.Ref<number, number>;
198
+ isFetched: vue.Ref<boolean, boolean>;
199
+ isFetchedAfterMount: vue.Ref<boolean, boolean>;
200
+ isFetching: vue.Ref<boolean, boolean>;
201
+ isInitialLoading: vue.Ref<boolean, boolean>;
202
+ isPaused: vue.Ref<boolean, boolean>;
203
+ isRefetching: vue.Ref<boolean, boolean>;
204
+ isStale: vue.Ref<boolean, boolean>;
205
+ isEnabled: vue.Ref<boolean, boolean>;
206
+ refetch: (options?: _tanstack_vue_query.RefetchOptions) => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
207
+ fetchStatus: vue.Ref<_tanstack_vue_query.FetchStatus, _tanstack_vue_query.FetchStatus>;
208
+ promise: vue.Ref<Promise<LaravelPaginationResponse<T>>, Promise<LaravelPaginationResponse<T>>>;
209
+ suspense: () => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
210
+ currentPage: vue.Ref<number, number>;
211
+ perPage: vue.Ref<number, number>;
212
+ search: vue.Ref<string, string>;
213
+ sortBy: vue.Ref<string | null, string | null>;
214
+ sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
215
+ filters: vue.ComputedRef<PaginationFilters>;
216
+ } | {
217
+ tableData: vue.ComputedRef<T[]>;
218
+ pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
219
+ handlePageChange: (page: number) => void;
220
+ handlePerPageChange: (newPerPage: number) => void;
221
+ handleSearchChange: (newSearch: string) => void;
222
+ handleSortChange: (column: string) => void;
223
+ resetFilters: () => void;
224
+ setFilter: (key: string, value: any) => void;
225
+ removeFilter: (key: string) => void;
226
+ getNumberingColumn: (options?: any) => {
227
+ accessorKey: string;
228
+ header: string;
229
+ enableSorting: boolean;
230
+ meta: {
231
+ style: {
232
+ width: string;
233
+ };
234
+ };
235
+ cell: ({ row }: any) => vue.VNode<vue.RendererNode, vue.RendererElement, {
236
+ [key: string]: any;
237
+ }>;
238
+ };
239
+ data: vue.Ref<undefined, undefined>;
240
+ error: vue.Ref<null, null>;
241
+ isError: vue.Ref<false, false>;
242
+ isPending: vue.Ref<true, true>;
243
+ isLoading: vue.Ref<true, true>;
244
+ isLoadingError: vue.Ref<false, false>;
245
+ isRefetchError: vue.Ref<false, false>;
246
+ isSuccess: vue.Ref<false, false>;
247
+ isPlaceholderData: vue.Ref<false, false>;
248
+ status: vue.Ref<"pending", "pending">;
249
+ dataUpdatedAt: vue.Ref<number, number>;
250
+ errorUpdatedAt: vue.Ref<number, number>;
251
+ failureCount: vue.Ref<number, number>;
252
+ failureReason: vue.Ref<Error | null, Error | null>;
253
+ errorUpdateCount: vue.Ref<number, number>;
254
+ isFetched: vue.Ref<boolean, boolean>;
255
+ isFetchedAfterMount: vue.Ref<boolean, boolean>;
256
+ isFetching: vue.Ref<boolean, boolean>;
257
+ isInitialLoading: vue.Ref<boolean, boolean>;
258
+ isPaused: vue.Ref<boolean, boolean>;
259
+ isRefetching: vue.Ref<boolean, boolean>;
260
+ isStale: vue.Ref<boolean, boolean>;
261
+ isEnabled: vue.Ref<boolean, boolean>;
262
+ refetch: (options?: _tanstack_vue_query.RefetchOptions) => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
263
+ fetchStatus: vue.Ref<_tanstack_vue_query.FetchStatus, _tanstack_vue_query.FetchStatus>;
264
+ promise: vue.Ref<Promise<LaravelPaginationResponse<T>>, Promise<LaravelPaginationResponse<T>>>;
265
+ suspense: () => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
266
+ currentPage: vue.Ref<number, number>;
267
+ perPage: vue.Ref<number, number>;
268
+ search: vue.Ref<string, string>;
269
+ sortBy: vue.Ref<string | null, string | null>;
270
+ sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
271
+ filters: vue.ComputedRef<PaginationFilters>;
272
+ } | {
273
+ tableData: vue.ComputedRef<T[]>;
274
+ pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
275
+ handlePageChange: (page: number) => void;
276
+ handlePerPageChange: (newPerPage: number) => void;
277
+ handleSearchChange: (newSearch: string) => void;
278
+ handleSortChange: (column: string) => void;
279
+ resetFilters: () => void;
280
+ setFilter: (key: string, value: any) => void;
281
+ removeFilter: (key: string) => void;
282
+ getNumberingColumn: (options?: any) => {
283
+ accessorKey: string;
284
+ header: string;
285
+ enableSorting: boolean;
286
+ meta: {
287
+ style: {
288
+ width: string;
289
+ };
290
+ };
291
+ cell: ({ row }: any) => vue.VNode<vue.RendererNode, vue.RendererElement, {
292
+ [key: string]: any;
293
+ }>;
294
+ };
295
+ data: vue.Ref<undefined, undefined>;
296
+ error: vue.Ref<null, null>;
297
+ isError: vue.Ref<false, false>;
298
+ isPending: vue.Ref<true, true>;
299
+ isLoadingError: vue.Ref<false, false>;
300
+ isRefetchError: vue.Ref<false, false>;
301
+ isSuccess: vue.Ref<false, false>;
302
+ isPlaceholderData: vue.Ref<false, false>;
303
+ status: vue.Ref<"pending", "pending">;
304
+ dataUpdatedAt: vue.Ref<number, number>;
305
+ errorUpdatedAt: vue.Ref<number, number>;
306
+ failureCount: vue.Ref<number, number>;
307
+ failureReason: vue.Ref<Error | null, Error | null>;
308
+ errorUpdateCount: vue.Ref<number, number>;
309
+ isFetched: vue.Ref<boolean, boolean>;
310
+ isFetchedAfterMount: vue.Ref<boolean, boolean>;
311
+ isFetching: vue.Ref<boolean, boolean>;
312
+ isLoading: vue.Ref<boolean, boolean>;
313
+ isInitialLoading: vue.Ref<boolean, boolean>;
314
+ isPaused: vue.Ref<boolean, boolean>;
315
+ isRefetching: vue.Ref<boolean, boolean>;
316
+ isStale: vue.Ref<boolean, boolean>;
317
+ isEnabled: vue.Ref<boolean, boolean>;
318
+ refetch: (options?: _tanstack_vue_query.RefetchOptions) => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
319
+ fetchStatus: vue.Ref<_tanstack_vue_query.FetchStatus, _tanstack_vue_query.FetchStatus>;
320
+ promise: vue.Ref<Promise<LaravelPaginationResponse<T>>, Promise<LaravelPaginationResponse<T>>>;
321
+ suspense: () => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
322
+ currentPage: vue.Ref<number, number>;
323
+ perPage: vue.Ref<number, number>;
324
+ search: vue.Ref<string, string>;
325
+ sortBy: vue.Ref<string | null, string | null>;
326
+ sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
327
+ filters: vue.ComputedRef<PaginationFilters>;
328
+ } | {
329
+ tableData: vue.ComputedRef<T[]>;
330
+ pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
331
+ handlePageChange: (page: number) => void;
332
+ handlePerPageChange: (newPerPage: number) => void;
333
+ handleSearchChange: (newSearch: string) => void;
334
+ handleSortChange: (column: string) => void;
335
+ resetFilters: () => void;
336
+ setFilter: (key: string, value: any) => void;
337
+ removeFilter: (key: string) => void;
338
+ getNumberingColumn: (options?: any) => {
339
+ accessorKey: string;
340
+ header: string;
341
+ enableSorting: boolean;
342
+ meta: {
343
+ style: {
344
+ width: string;
345
+ };
346
+ };
347
+ cell: ({ row }: any) => vue.VNode<vue.RendererNode, vue.RendererElement, {
348
+ [key: string]: any;
349
+ }>;
350
+ };
351
+ data: vue.Ref<LaravelPaginationResponse<T>, LaravelPaginationResponse<T>>;
352
+ isError: vue.Ref<false, false>;
353
+ error: vue.Ref<null, null>;
354
+ isPending: vue.Ref<false, false>;
355
+ isLoading: vue.Ref<false, false>;
356
+ isLoadingError: vue.Ref<false, false>;
357
+ isRefetchError: vue.Ref<false, false>;
358
+ isSuccess: vue.Ref<true, true>;
359
+ isPlaceholderData: vue.Ref<true, true>;
360
+ status: vue.Ref<"success", "success">;
361
+ dataUpdatedAt: vue.Ref<number, number>;
362
+ errorUpdatedAt: vue.Ref<number, number>;
363
+ failureCount: vue.Ref<number, number>;
364
+ failureReason: vue.Ref<Error | null, Error | null>;
365
+ errorUpdateCount: vue.Ref<number, number>;
366
+ isFetched: vue.Ref<boolean, boolean>;
367
+ isFetchedAfterMount: vue.Ref<boolean, boolean>;
368
+ isFetching: vue.Ref<boolean, boolean>;
369
+ isInitialLoading: vue.Ref<boolean, boolean>;
370
+ isPaused: vue.Ref<boolean, boolean>;
371
+ isRefetching: vue.Ref<boolean, boolean>;
372
+ isStale: vue.Ref<boolean, boolean>;
373
+ isEnabled: vue.Ref<boolean, boolean>;
374
+ refetch: (options?: _tanstack_vue_query.RefetchOptions) => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
375
+ fetchStatus: vue.Ref<_tanstack_vue_query.FetchStatus, _tanstack_vue_query.FetchStatus>;
376
+ promise: vue.Ref<Promise<LaravelPaginationResponse<T>>, Promise<LaravelPaginationResponse<T>>>;
377
+ suspense: () => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
378
+ currentPage: vue.Ref<number, number>;
379
+ perPage: vue.Ref<number, number>;
380
+ search: vue.Ref<string, string>;
381
+ sortBy: vue.Ref<string | null, string | null>;
382
+ sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
383
+ filters: vue.ComputedRef<PaginationFilters>;
384
+ };
385
+
386
+ interface NumberingOptions {
387
+ header?: string;
388
+ className?: string;
389
+ width?: string;
390
+ enableSorting?: boolean;
391
+ }
392
+ declare function useTableNumbering(): {
393
+ createNumberingColumn: <T = any>(pagination: Ref<LaravelPaginationResponse<T> | null> | ComputedRef<LaravelPaginationResponse<T> | null>, perPage: Ref<number>, options?: NumberingOptions) => {
394
+ accessorKey: string;
395
+ header: string;
396
+ enableSorting: boolean;
397
+ meta: {
398
+ style: {
399
+ width: string;
400
+ };
401
+ };
402
+ cell: ({ row }: any) => vue.VNode<vue.RendererNode, vue.RendererElement, {
403
+ [key: string]: any;
404
+ }>;
405
+ };
406
+ calculateSequentialNumber: (rowIndex: number, currentPage: number, perPageValue: number) => number;
407
+ getPageStartNumber: (currentPage: number, perPageValue: number) => number;
408
+ getPageEndNumber: <T = any>(pagination: LaravelPaginationResponse<T>) => number;
409
+ getPaginationInfo: <T = any>(pagination: LaravelPaginationResponse<T>) => string;
410
+ hasPage: <T = any>(pagination: LaravelPaginationResponse<T>, page: number) => boolean;
411
+ getPageRange: <T = any>(pagination: LaravelPaginationResponse<T>, maxPages?: number) => number[];
412
+ };
413
+
414
+ export { type LaravelPaginationResponse, type PaginationFilters, type SortState, type UsePaginationOptions, usePagination, useTableNumbering };
@@ -0,0 +1,414 @@
1
+ import * as _tanstack_vue_query from '@tanstack/vue-query';
2
+ import { UseQueryOptions } from '@tanstack/vue-query';
3
+ import * as vue from 'vue';
4
+ import { Ref, ComputedRef } from 'vue';
5
+
6
+ type LaravelPaginationResponse<T = any> = {
7
+ data: T[];
8
+ links: Array<{
9
+ first: string | null;
10
+ last: string | null;
11
+ next: string | null;
12
+ prev: string | null;
13
+ }>;
14
+ meta: {
15
+ current_page: number;
16
+ from: number;
17
+ last_page: number;
18
+ links: Array<{
19
+ url: string | null;
20
+ label: string;
21
+ active: boolean;
22
+ }>;
23
+ path: string;
24
+ per_page: number;
25
+ to: number;
26
+ total: number;
27
+ };
28
+ };
29
+ interface PaginationFilters {
30
+ page?: number;
31
+ per_page?: number;
32
+ search?: string;
33
+ sort_by?: string;
34
+ sort_direction?: 'asc' | 'desc';
35
+ [key: string]: any;
36
+ }
37
+ interface SortState {
38
+ column: string | null;
39
+ direction: 'asc' | 'desc';
40
+ }
41
+
42
+ interface UsePaginationOptions<T> extends Omit<UseQueryOptions<LaravelPaginationResponse<T>>, 'queryKey' | 'queryFn'> {
43
+ queryKey: string;
44
+ defaultPerPage?: number;
45
+ defaultSearch?: string;
46
+ defaultSort?: SortState;
47
+ }
48
+ declare function usePagination<T = any>(fetchFn: (filters: PaginationFilters) => Promise<LaravelPaginationResponse<T>>, options: UsePaginationOptions<T>): {
49
+ tableData: vue.ComputedRef<T[]>;
50
+ pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
51
+ handlePageChange: (page: number) => void;
52
+ handlePerPageChange: (newPerPage: number) => void;
53
+ handleSearchChange: (newSearch: string) => void;
54
+ handleSortChange: (column: string) => void;
55
+ resetFilters: () => void;
56
+ setFilter: (key: string, value: any) => void;
57
+ removeFilter: (key: string) => void;
58
+ getNumberingColumn: (options?: any) => {
59
+ accessorKey: string;
60
+ header: string;
61
+ enableSorting: boolean;
62
+ meta: {
63
+ style: {
64
+ width: string;
65
+ };
66
+ };
67
+ cell: ({ row }: any) => vue.VNode<vue.RendererNode, vue.RendererElement, {
68
+ [key: string]: any;
69
+ }>;
70
+ };
71
+ data: vue.Ref<LaravelPaginationResponse<T>, LaravelPaginationResponse<T>>;
72
+ error: vue.Ref<Error, Error>;
73
+ isError: vue.Ref<true, true>;
74
+ isPending: vue.Ref<false, false>;
75
+ isLoading: vue.Ref<false, false>;
76
+ isLoadingError: vue.Ref<false, false>;
77
+ isRefetchError: vue.Ref<true, true>;
78
+ isSuccess: vue.Ref<false, false>;
79
+ isPlaceholderData: vue.Ref<false, false>;
80
+ status: vue.Ref<"error", "error">;
81
+ dataUpdatedAt: vue.Ref<number, number>;
82
+ errorUpdatedAt: vue.Ref<number, number>;
83
+ failureCount: vue.Ref<number, number>;
84
+ failureReason: vue.Ref<Error | null, Error | null>;
85
+ errorUpdateCount: vue.Ref<number, number>;
86
+ isFetched: vue.Ref<boolean, boolean>;
87
+ isFetchedAfterMount: vue.Ref<boolean, boolean>;
88
+ isFetching: vue.Ref<boolean, boolean>;
89
+ isInitialLoading: vue.Ref<boolean, boolean>;
90
+ isPaused: vue.Ref<boolean, boolean>;
91
+ isRefetching: vue.Ref<boolean, boolean>;
92
+ isStale: vue.Ref<boolean, boolean>;
93
+ isEnabled: vue.Ref<boolean, boolean>;
94
+ refetch: (options?: _tanstack_vue_query.RefetchOptions) => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
95
+ fetchStatus: vue.Ref<_tanstack_vue_query.FetchStatus, _tanstack_vue_query.FetchStatus>;
96
+ promise: vue.Ref<Promise<LaravelPaginationResponse<T>>, Promise<LaravelPaginationResponse<T>>>;
97
+ suspense: () => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
98
+ currentPage: vue.Ref<number, number>;
99
+ perPage: vue.Ref<number, number>;
100
+ search: vue.Ref<string, string>;
101
+ sortBy: vue.Ref<string | null, string | null>;
102
+ sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
103
+ filters: vue.ComputedRef<PaginationFilters>;
104
+ } | {
105
+ tableData: vue.ComputedRef<T[]>;
106
+ pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
107
+ handlePageChange: (page: number) => void;
108
+ handlePerPageChange: (newPerPage: number) => void;
109
+ handleSearchChange: (newSearch: string) => void;
110
+ handleSortChange: (column: string) => void;
111
+ resetFilters: () => void;
112
+ setFilter: (key: string, value: any) => void;
113
+ removeFilter: (key: string) => void;
114
+ getNumberingColumn: (options?: any) => {
115
+ accessorKey: string;
116
+ header: string;
117
+ enableSorting: boolean;
118
+ meta: {
119
+ style: {
120
+ width: string;
121
+ };
122
+ };
123
+ cell: ({ row }: any) => vue.VNode<vue.RendererNode, vue.RendererElement, {
124
+ [key: string]: any;
125
+ }>;
126
+ };
127
+ data: vue.Ref<LaravelPaginationResponse<T>, LaravelPaginationResponse<T>>;
128
+ error: vue.Ref<null, null>;
129
+ isError: vue.Ref<false, false>;
130
+ isPending: vue.Ref<false, false>;
131
+ isLoading: vue.Ref<false, false>;
132
+ isLoadingError: vue.Ref<false, false>;
133
+ isRefetchError: vue.Ref<false, false>;
134
+ isSuccess: vue.Ref<true, true>;
135
+ isPlaceholderData: vue.Ref<false, false>;
136
+ status: vue.Ref<"success", "success">;
137
+ dataUpdatedAt: vue.Ref<number, number>;
138
+ errorUpdatedAt: vue.Ref<number, number>;
139
+ failureCount: vue.Ref<number, number>;
140
+ failureReason: vue.Ref<Error | null, Error | null>;
141
+ errorUpdateCount: vue.Ref<number, number>;
142
+ isFetched: vue.Ref<boolean, boolean>;
143
+ isFetchedAfterMount: vue.Ref<boolean, boolean>;
144
+ isFetching: vue.Ref<boolean, boolean>;
145
+ isInitialLoading: vue.Ref<boolean, boolean>;
146
+ isPaused: vue.Ref<boolean, boolean>;
147
+ isRefetching: vue.Ref<boolean, boolean>;
148
+ isStale: vue.Ref<boolean, boolean>;
149
+ isEnabled: vue.Ref<boolean, boolean>;
150
+ refetch: (options?: _tanstack_vue_query.RefetchOptions) => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
151
+ fetchStatus: vue.Ref<_tanstack_vue_query.FetchStatus, _tanstack_vue_query.FetchStatus>;
152
+ promise: vue.Ref<Promise<LaravelPaginationResponse<T>>, Promise<LaravelPaginationResponse<T>>>;
153
+ suspense: () => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
154
+ currentPage: vue.Ref<number, number>;
155
+ perPage: vue.Ref<number, number>;
156
+ search: vue.Ref<string, string>;
157
+ sortBy: vue.Ref<string | null, string | null>;
158
+ sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
159
+ filters: vue.ComputedRef<PaginationFilters>;
160
+ } | {
161
+ tableData: vue.ComputedRef<T[]>;
162
+ pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
163
+ handlePageChange: (page: number) => void;
164
+ handlePerPageChange: (newPerPage: number) => void;
165
+ handleSearchChange: (newSearch: string) => void;
166
+ handleSortChange: (column: string) => void;
167
+ resetFilters: () => void;
168
+ setFilter: (key: string, value: any) => void;
169
+ removeFilter: (key: string) => void;
170
+ getNumberingColumn: (options?: any) => {
171
+ accessorKey: string;
172
+ header: string;
173
+ enableSorting: boolean;
174
+ meta: {
175
+ style: {
176
+ width: string;
177
+ };
178
+ };
179
+ cell: ({ row }: any) => vue.VNode<vue.RendererNode, vue.RendererElement, {
180
+ [key: string]: any;
181
+ }>;
182
+ };
183
+ data: vue.Ref<undefined, undefined>;
184
+ error: vue.Ref<Error, Error>;
185
+ isError: vue.Ref<true, true>;
186
+ isPending: vue.Ref<false, false>;
187
+ isLoading: vue.Ref<false, false>;
188
+ isLoadingError: vue.Ref<true, true>;
189
+ isRefetchError: vue.Ref<false, false>;
190
+ isSuccess: vue.Ref<false, false>;
191
+ isPlaceholderData: vue.Ref<false, false>;
192
+ status: vue.Ref<"error", "error">;
193
+ dataUpdatedAt: vue.Ref<number, number>;
194
+ errorUpdatedAt: vue.Ref<number, number>;
195
+ failureCount: vue.Ref<number, number>;
196
+ failureReason: vue.Ref<Error | null, Error | null>;
197
+ errorUpdateCount: vue.Ref<number, number>;
198
+ isFetched: vue.Ref<boolean, boolean>;
199
+ isFetchedAfterMount: vue.Ref<boolean, boolean>;
200
+ isFetching: vue.Ref<boolean, boolean>;
201
+ isInitialLoading: vue.Ref<boolean, boolean>;
202
+ isPaused: vue.Ref<boolean, boolean>;
203
+ isRefetching: vue.Ref<boolean, boolean>;
204
+ isStale: vue.Ref<boolean, boolean>;
205
+ isEnabled: vue.Ref<boolean, boolean>;
206
+ refetch: (options?: _tanstack_vue_query.RefetchOptions) => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
207
+ fetchStatus: vue.Ref<_tanstack_vue_query.FetchStatus, _tanstack_vue_query.FetchStatus>;
208
+ promise: vue.Ref<Promise<LaravelPaginationResponse<T>>, Promise<LaravelPaginationResponse<T>>>;
209
+ suspense: () => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
210
+ currentPage: vue.Ref<number, number>;
211
+ perPage: vue.Ref<number, number>;
212
+ search: vue.Ref<string, string>;
213
+ sortBy: vue.Ref<string | null, string | null>;
214
+ sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
215
+ filters: vue.ComputedRef<PaginationFilters>;
216
+ } | {
217
+ tableData: vue.ComputedRef<T[]>;
218
+ pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
219
+ handlePageChange: (page: number) => void;
220
+ handlePerPageChange: (newPerPage: number) => void;
221
+ handleSearchChange: (newSearch: string) => void;
222
+ handleSortChange: (column: string) => void;
223
+ resetFilters: () => void;
224
+ setFilter: (key: string, value: any) => void;
225
+ removeFilter: (key: string) => void;
226
+ getNumberingColumn: (options?: any) => {
227
+ accessorKey: string;
228
+ header: string;
229
+ enableSorting: boolean;
230
+ meta: {
231
+ style: {
232
+ width: string;
233
+ };
234
+ };
235
+ cell: ({ row }: any) => vue.VNode<vue.RendererNode, vue.RendererElement, {
236
+ [key: string]: any;
237
+ }>;
238
+ };
239
+ data: vue.Ref<undefined, undefined>;
240
+ error: vue.Ref<null, null>;
241
+ isError: vue.Ref<false, false>;
242
+ isPending: vue.Ref<true, true>;
243
+ isLoading: vue.Ref<true, true>;
244
+ isLoadingError: vue.Ref<false, false>;
245
+ isRefetchError: vue.Ref<false, false>;
246
+ isSuccess: vue.Ref<false, false>;
247
+ isPlaceholderData: vue.Ref<false, false>;
248
+ status: vue.Ref<"pending", "pending">;
249
+ dataUpdatedAt: vue.Ref<number, number>;
250
+ errorUpdatedAt: vue.Ref<number, number>;
251
+ failureCount: vue.Ref<number, number>;
252
+ failureReason: vue.Ref<Error | null, Error | null>;
253
+ errorUpdateCount: vue.Ref<number, number>;
254
+ isFetched: vue.Ref<boolean, boolean>;
255
+ isFetchedAfterMount: vue.Ref<boolean, boolean>;
256
+ isFetching: vue.Ref<boolean, boolean>;
257
+ isInitialLoading: vue.Ref<boolean, boolean>;
258
+ isPaused: vue.Ref<boolean, boolean>;
259
+ isRefetching: vue.Ref<boolean, boolean>;
260
+ isStale: vue.Ref<boolean, boolean>;
261
+ isEnabled: vue.Ref<boolean, boolean>;
262
+ refetch: (options?: _tanstack_vue_query.RefetchOptions) => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
263
+ fetchStatus: vue.Ref<_tanstack_vue_query.FetchStatus, _tanstack_vue_query.FetchStatus>;
264
+ promise: vue.Ref<Promise<LaravelPaginationResponse<T>>, Promise<LaravelPaginationResponse<T>>>;
265
+ suspense: () => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
266
+ currentPage: vue.Ref<number, number>;
267
+ perPage: vue.Ref<number, number>;
268
+ search: vue.Ref<string, string>;
269
+ sortBy: vue.Ref<string | null, string | null>;
270
+ sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
271
+ filters: vue.ComputedRef<PaginationFilters>;
272
+ } | {
273
+ tableData: vue.ComputedRef<T[]>;
274
+ pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
275
+ handlePageChange: (page: number) => void;
276
+ handlePerPageChange: (newPerPage: number) => void;
277
+ handleSearchChange: (newSearch: string) => void;
278
+ handleSortChange: (column: string) => void;
279
+ resetFilters: () => void;
280
+ setFilter: (key: string, value: any) => void;
281
+ removeFilter: (key: string) => void;
282
+ getNumberingColumn: (options?: any) => {
283
+ accessorKey: string;
284
+ header: string;
285
+ enableSorting: boolean;
286
+ meta: {
287
+ style: {
288
+ width: string;
289
+ };
290
+ };
291
+ cell: ({ row }: any) => vue.VNode<vue.RendererNode, vue.RendererElement, {
292
+ [key: string]: any;
293
+ }>;
294
+ };
295
+ data: vue.Ref<undefined, undefined>;
296
+ error: vue.Ref<null, null>;
297
+ isError: vue.Ref<false, false>;
298
+ isPending: vue.Ref<true, true>;
299
+ isLoadingError: vue.Ref<false, false>;
300
+ isRefetchError: vue.Ref<false, false>;
301
+ isSuccess: vue.Ref<false, false>;
302
+ isPlaceholderData: vue.Ref<false, false>;
303
+ status: vue.Ref<"pending", "pending">;
304
+ dataUpdatedAt: vue.Ref<number, number>;
305
+ errorUpdatedAt: vue.Ref<number, number>;
306
+ failureCount: vue.Ref<number, number>;
307
+ failureReason: vue.Ref<Error | null, Error | null>;
308
+ errorUpdateCount: vue.Ref<number, number>;
309
+ isFetched: vue.Ref<boolean, boolean>;
310
+ isFetchedAfterMount: vue.Ref<boolean, boolean>;
311
+ isFetching: vue.Ref<boolean, boolean>;
312
+ isLoading: vue.Ref<boolean, boolean>;
313
+ isInitialLoading: vue.Ref<boolean, boolean>;
314
+ isPaused: vue.Ref<boolean, boolean>;
315
+ isRefetching: vue.Ref<boolean, boolean>;
316
+ isStale: vue.Ref<boolean, boolean>;
317
+ isEnabled: vue.Ref<boolean, boolean>;
318
+ refetch: (options?: _tanstack_vue_query.RefetchOptions) => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
319
+ fetchStatus: vue.Ref<_tanstack_vue_query.FetchStatus, _tanstack_vue_query.FetchStatus>;
320
+ promise: vue.Ref<Promise<LaravelPaginationResponse<T>>, Promise<LaravelPaginationResponse<T>>>;
321
+ suspense: () => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
322
+ currentPage: vue.Ref<number, number>;
323
+ perPage: vue.Ref<number, number>;
324
+ search: vue.Ref<string, string>;
325
+ sortBy: vue.Ref<string | null, string | null>;
326
+ sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
327
+ filters: vue.ComputedRef<PaginationFilters>;
328
+ } | {
329
+ tableData: vue.ComputedRef<T[]>;
330
+ pagination: vue.ComputedRef<LaravelPaginationResponse<T> | null>;
331
+ handlePageChange: (page: number) => void;
332
+ handlePerPageChange: (newPerPage: number) => void;
333
+ handleSearchChange: (newSearch: string) => void;
334
+ handleSortChange: (column: string) => void;
335
+ resetFilters: () => void;
336
+ setFilter: (key: string, value: any) => void;
337
+ removeFilter: (key: string) => void;
338
+ getNumberingColumn: (options?: any) => {
339
+ accessorKey: string;
340
+ header: string;
341
+ enableSorting: boolean;
342
+ meta: {
343
+ style: {
344
+ width: string;
345
+ };
346
+ };
347
+ cell: ({ row }: any) => vue.VNode<vue.RendererNode, vue.RendererElement, {
348
+ [key: string]: any;
349
+ }>;
350
+ };
351
+ data: vue.Ref<LaravelPaginationResponse<T>, LaravelPaginationResponse<T>>;
352
+ isError: vue.Ref<false, false>;
353
+ error: vue.Ref<null, null>;
354
+ isPending: vue.Ref<false, false>;
355
+ isLoading: vue.Ref<false, false>;
356
+ isLoadingError: vue.Ref<false, false>;
357
+ isRefetchError: vue.Ref<false, false>;
358
+ isSuccess: vue.Ref<true, true>;
359
+ isPlaceholderData: vue.Ref<true, true>;
360
+ status: vue.Ref<"success", "success">;
361
+ dataUpdatedAt: vue.Ref<number, number>;
362
+ errorUpdatedAt: vue.Ref<number, number>;
363
+ failureCount: vue.Ref<number, number>;
364
+ failureReason: vue.Ref<Error | null, Error | null>;
365
+ errorUpdateCount: vue.Ref<number, number>;
366
+ isFetched: vue.Ref<boolean, boolean>;
367
+ isFetchedAfterMount: vue.Ref<boolean, boolean>;
368
+ isFetching: vue.Ref<boolean, boolean>;
369
+ isInitialLoading: vue.Ref<boolean, boolean>;
370
+ isPaused: vue.Ref<boolean, boolean>;
371
+ isRefetching: vue.Ref<boolean, boolean>;
372
+ isStale: vue.Ref<boolean, boolean>;
373
+ isEnabled: vue.Ref<boolean, boolean>;
374
+ refetch: (options?: _tanstack_vue_query.RefetchOptions) => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
375
+ fetchStatus: vue.Ref<_tanstack_vue_query.FetchStatus, _tanstack_vue_query.FetchStatus>;
376
+ promise: vue.Ref<Promise<LaravelPaginationResponse<T>>, Promise<LaravelPaginationResponse<T>>>;
377
+ suspense: () => Promise<_tanstack_vue_query.QueryObserverResult<LaravelPaginationResponse<T>, Error>>;
378
+ currentPage: vue.Ref<number, number>;
379
+ perPage: vue.Ref<number, number>;
380
+ search: vue.Ref<string, string>;
381
+ sortBy: vue.Ref<string | null, string | null>;
382
+ sortDirection: vue.Ref<"asc" | "desc", "asc" | "desc">;
383
+ filters: vue.ComputedRef<PaginationFilters>;
384
+ };
385
+
386
+ interface NumberingOptions {
387
+ header?: string;
388
+ className?: string;
389
+ width?: string;
390
+ enableSorting?: boolean;
391
+ }
392
+ declare function useTableNumbering(): {
393
+ createNumberingColumn: <T = any>(pagination: Ref<LaravelPaginationResponse<T> | null> | ComputedRef<LaravelPaginationResponse<T> | null>, perPage: Ref<number>, options?: NumberingOptions) => {
394
+ accessorKey: string;
395
+ header: string;
396
+ enableSorting: boolean;
397
+ meta: {
398
+ style: {
399
+ width: string;
400
+ };
401
+ };
402
+ cell: ({ row }: any) => vue.VNode<vue.RendererNode, vue.RendererElement, {
403
+ [key: string]: any;
404
+ }>;
405
+ };
406
+ calculateSequentialNumber: (rowIndex: number, currentPage: number, perPageValue: number) => number;
407
+ getPageStartNumber: (currentPage: number, perPageValue: number) => number;
408
+ getPageEndNumber: <T = any>(pagination: LaravelPaginationResponse<T>) => number;
409
+ getPaginationInfo: <T = any>(pagination: LaravelPaginationResponse<T>) => string;
410
+ hasPage: <T = any>(pagination: LaravelPaginationResponse<T>, page: number) => boolean;
411
+ getPageRange: <T = any>(pagination: LaravelPaginationResponse<T>, maxPages?: number) => number[];
412
+ };
413
+
414
+ export { type LaravelPaginationResponse, type PaginationFilters, type SortState, type UsePaginationOptions, usePagination, useTableNumbering };
package/dist/index.js ADDED
@@ -0,0 +1,200 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ usePagination: () => usePagination,
24
+ useTableNumbering: () => useTableNumbering
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/composables/useTableNumbering.ts
29
+ var import_vue = require("vue");
30
+ function useTableNumbering() {
31
+ const createNumberingColumn = (pagination, perPage, options = {}) => {
32
+ const {
33
+ header = "No.",
34
+ className = "text-center text-ubd-ocean-700 dark:text-ubd-ocean-200 font-medium",
35
+ width = "60px",
36
+ enableSorting = false
37
+ } = options;
38
+ return {
39
+ accessorKey: "no",
40
+ header,
41
+ enableSorting,
42
+ meta: {
43
+ style: { width }
44
+ },
45
+ cell: ({ row }) => {
46
+ const currentPage = pagination.value?.meta?.current_page || 1;
47
+ const perPageValue = perPage.value || 10;
48
+ const rowIndex = row.index;
49
+ const sequentialNumber = (currentPage - 1) * perPageValue + rowIndex + 1;
50
+ return (0, import_vue.h)("span", { class: className }, sequentialNumber.toString());
51
+ }
52
+ };
53
+ };
54
+ const calculateSequentialNumber = (rowIndex, currentPage, perPageValue) => {
55
+ return (currentPage - 1) * perPageValue + rowIndex + 1;
56
+ };
57
+ const getPageStartNumber = (currentPage, perPageValue) => {
58
+ return (currentPage - 1) * perPageValue + 1;
59
+ };
60
+ const getPageEndNumber = (pagination) => {
61
+ return pagination.meta.from + pagination.data.length - 1;
62
+ };
63
+ const getPaginationInfo = (pagination) => {
64
+ if (!pagination.data.length) {
65
+ return "No results found";
66
+ }
67
+ const { from, to, total } = pagination.meta;
68
+ return `Showing ${from} to ${to} of ${total} results`;
69
+ };
70
+ const hasPage = (pagination, page) => {
71
+ return page >= 1 && page <= pagination.meta.last_page;
72
+ };
73
+ const getPageRange = (pagination, maxPages = 5) => {
74
+ const { current_page, last_page } = pagination.meta;
75
+ const pages = [];
76
+ let start = Math.max(1, current_page - Math.floor(maxPages / 2));
77
+ const end = Math.min(last_page, start + maxPages - 1);
78
+ if (end - start + 1 < maxPages) {
79
+ start = Math.max(1, end - maxPages + 1);
80
+ }
81
+ for (let i = start; i <= end; i++) {
82
+ pages.push(i);
83
+ }
84
+ return pages;
85
+ };
86
+ return {
87
+ createNumberingColumn,
88
+ calculateSequentialNumber,
89
+ getPageStartNumber,
90
+ getPageEndNumber,
91
+ getPaginationInfo,
92
+ hasPage,
93
+ getPageRange
94
+ };
95
+ }
96
+
97
+ // src/composables/usePagination.ts
98
+ var import_vue_query = require("@tanstack/vue-query");
99
+ var import_vue2 = require("vue");
100
+ function usePagination(fetchFn, options) {
101
+ const currentPage = (0, import_vue2.ref)(1);
102
+ const perPage = (0, import_vue2.ref)(options.defaultPerPage || 10);
103
+ const search = (0, import_vue2.ref)(options.defaultSearch || "");
104
+ const sortBy = (0, import_vue2.ref)(options.defaultSort?.column || null);
105
+ const sortDirection = (0, import_vue2.ref)(options.defaultSort?.direction || "asc");
106
+ const filters = (0, import_vue2.computed)(() => {
107
+ const baseFilters = {
108
+ page: currentPage.value,
109
+ per_page: perPage.value,
110
+ search: search.value
111
+ };
112
+ if (sortBy.value) {
113
+ baseFilters[`sort[${sortBy.value}]`] = sortDirection.value;
114
+ }
115
+ return baseFilters;
116
+ });
117
+ const queryResult = (0, import_vue_query.useQuery)({
118
+ ...options,
119
+ queryKey: [options.queryKey, filters],
120
+ queryFn: () => fetchFn(filters.value),
121
+ refetchOnWindowFocus: false
122
+ });
123
+ const tableData = (0, import_vue2.computed)(() => queryResult.data.value?.data || []);
124
+ const pagination = (0, import_vue2.computed)(() => queryResult.data.value || null);
125
+ const handlePageChange = (page) => {
126
+ currentPage.value = page;
127
+ };
128
+ const handlePerPageChange = (newPerPage) => {
129
+ perPage.value = newPerPage;
130
+ currentPage.value = 1;
131
+ };
132
+ const handleSearchChange = (newSearch) => {
133
+ search.value = newSearch;
134
+ currentPage.value = 1;
135
+ };
136
+ const handleSortChange = (column) => {
137
+ if (sortBy.value === column) {
138
+ sortDirection.value = sortDirection.value === "asc" ? "desc" : "asc";
139
+ } else {
140
+ sortBy.value = column;
141
+ sortDirection.value = "asc";
142
+ }
143
+ currentPage.value = 1;
144
+ };
145
+ const setFilter = (key, value) => {
146
+ filters.value[key] = value;
147
+ currentPage.value = 1;
148
+ };
149
+ const removeFilter = (key) => {
150
+ delete filters.value[key];
151
+ currentPage.value = 1;
152
+ };
153
+ const resetFilters = () => {
154
+ currentPage.value = 1;
155
+ perPage.value = options.defaultPerPage || 10;
156
+ search.value = options.defaultSearch || "";
157
+ sortBy.value = options.defaultSort?.column || null;
158
+ sortDirection.value = options.defaultSort?.direction || "asc";
159
+ };
160
+ let searchTimeout;
161
+ (0, import_vue2.watch)(search, () => {
162
+ clearTimeout(searchTimeout);
163
+ searchTimeout = window.setTimeout(() => {
164
+ currentPage.value = 1;
165
+ }, 300);
166
+ });
167
+ const { createNumberingColumn } = useTableNumbering();
168
+ const getNumberingColumn = (options2 = {}) => {
169
+ return createNumberingColumn(pagination, perPage, options2);
170
+ };
171
+ return {
172
+ // State
173
+ currentPage,
174
+ perPage,
175
+ search,
176
+ sortBy,
177
+ sortDirection,
178
+ filters,
179
+ // Query result
180
+ ...queryResult,
181
+ // Computed
182
+ tableData,
183
+ pagination,
184
+ // Actions
185
+ handlePageChange,
186
+ handlePerPageChange,
187
+ handleSearchChange,
188
+ handleSortChange,
189
+ resetFilters,
190
+ setFilter,
191
+ removeFilter,
192
+ // Helpers
193
+ getNumberingColumn
194
+ };
195
+ }
196
+ // Annotate the CommonJS export names for ESM import in node:
197
+ 0 && (module.exports = {
198
+ usePagination,
199
+ useTableNumbering
200
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,172 @@
1
+ // src/composables/useTableNumbering.ts
2
+ import { h } from "vue";
3
+ function useTableNumbering() {
4
+ const createNumberingColumn = (pagination, perPage, options = {}) => {
5
+ const {
6
+ header = "No.",
7
+ className = "text-center text-ubd-ocean-700 dark:text-ubd-ocean-200 font-medium",
8
+ width = "60px",
9
+ enableSorting = false
10
+ } = options;
11
+ return {
12
+ accessorKey: "no",
13
+ header,
14
+ enableSorting,
15
+ meta: {
16
+ style: { width }
17
+ },
18
+ cell: ({ row }) => {
19
+ const currentPage = pagination.value?.meta?.current_page || 1;
20
+ const perPageValue = perPage.value || 10;
21
+ const rowIndex = row.index;
22
+ const sequentialNumber = (currentPage - 1) * perPageValue + rowIndex + 1;
23
+ return h("span", { class: className }, sequentialNumber.toString());
24
+ }
25
+ };
26
+ };
27
+ const calculateSequentialNumber = (rowIndex, currentPage, perPageValue) => {
28
+ return (currentPage - 1) * perPageValue + rowIndex + 1;
29
+ };
30
+ const getPageStartNumber = (currentPage, perPageValue) => {
31
+ return (currentPage - 1) * perPageValue + 1;
32
+ };
33
+ const getPageEndNumber = (pagination) => {
34
+ return pagination.meta.from + pagination.data.length - 1;
35
+ };
36
+ const getPaginationInfo = (pagination) => {
37
+ if (!pagination.data.length) {
38
+ return "No results found";
39
+ }
40
+ const { from, to, total } = pagination.meta;
41
+ return `Showing ${from} to ${to} of ${total} results`;
42
+ };
43
+ const hasPage = (pagination, page) => {
44
+ return page >= 1 && page <= pagination.meta.last_page;
45
+ };
46
+ const getPageRange = (pagination, maxPages = 5) => {
47
+ const { current_page, last_page } = pagination.meta;
48
+ const pages = [];
49
+ let start = Math.max(1, current_page - Math.floor(maxPages / 2));
50
+ const end = Math.min(last_page, start + maxPages - 1);
51
+ if (end - start + 1 < maxPages) {
52
+ start = Math.max(1, end - maxPages + 1);
53
+ }
54
+ for (let i = start; i <= end; i++) {
55
+ pages.push(i);
56
+ }
57
+ return pages;
58
+ };
59
+ return {
60
+ createNumberingColumn,
61
+ calculateSequentialNumber,
62
+ getPageStartNumber,
63
+ getPageEndNumber,
64
+ getPaginationInfo,
65
+ hasPage,
66
+ getPageRange
67
+ };
68
+ }
69
+
70
+ // src/composables/usePagination.ts
71
+ import { useQuery } from "@tanstack/vue-query";
72
+ import { computed, ref, watch } from "vue";
73
+ function usePagination(fetchFn, options) {
74
+ const currentPage = ref(1);
75
+ const perPage = ref(options.defaultPerPage || 10);
76
+ const search = ref(options.defaultSearch || "");
77
+ const sortBy = ref(options.defaultSort?.column || null);
78
+ const sortDirection = ref(options.defaultSort?.direction || "asc");
79
+ const filters = computed(() => {
80
+ const baseFilters = {
81
+ page: currentPage.value,
82
+ per_page: perPage.value,
83
+ search: search.value
84
+ };
85
+ if (sortBy.value) {
86
+ baseFilters[`sort[${sortBy.value}]`] = sortDirection.value;
87
+ }
88
+ return baseFilters;
89
+ });
90
+ const queryResult = useQuery({
91
+ ...options,
92
+ queryKey: [options.queryKey, filters],
93
+ queryFn: () => fetchFn(filters.value),
94
+ refetchOnWindowFocus: false
95
+ });
96
+ const tableData = computed(() => queryResult.data.value?.data || []);
97
+ const pagination = computed(() => queryResult.data.value || null);
98
+ const handlePageChange = (page) => {
99
+ currentPage.value = page;
100
+ };
101
+ const handlePerPageChange = (newPerPage) => {
102
+ perPage.value = newPerPage;
103
+ currentPage.value = 1;
104
+ };
105
+ const handleSearchChange = (newSearch) => {
106
+ search.value = newSearch;
107
+ currentPage.value = 1;
108
+ };
109
+ const handleSortChange = (column) => {
110
+ if (sortBy.value === column) {
111
+ sortDirection.value = sortDirection.value === "asc" ? "desc" : "asc";
112
+ } else {
113
+ sortBy.value = column;
114
+ sortDirection.value = "asc";
115
+ }
116
+ currentPage.value = 1;
117
+ };
118
+ const setFilter = (key, value) => {
119
+ filters.value[key] = value;
120
+ currentPage.value = 1;
121
+ };
122
+ const removeFilter = (key) => {
123
+ delete filters.value[key];
124
+ currentPage.value = 1;
125
+ };
126
+ const resetFilters = () => {
127
+ currentPage.value = 1;
128
+ perPage.value = options.defaultPerPage || 10;
129
+ search.value = options.defaultSearch || "";
130
+ sortBy.value = options.defaultSort?.column || null;
131
+ sortDirection.value = options.defaultSort?.direction || "asc";
132
+ };
133
+ let searchTimeout;
134
+ watch(search, () => {
135
+ clearTimeout(searchTimeout);
136
+ searchTimeout = window.setTimeout(() => {
137
+ currentPage.value = 1;
138
+ }, 300);
139
+ });
140
+ const { createNumberingColumn } = useTableNumbering();
141
+ const getNumberingColumn = (options2 = {}) => {
142
+ return createNumberingColumn(pagination, perPage, options2);
143
+ };
144
+ return {
145
+ // State
146
+ currentPage,
147
+ perPage,
148
+ search,
149
+ sortBy,
150
+ sortDirection,
151
+ filters,
152
+ // Query result
153
+ ...queryResult,
154
+ // Computed
155
+ tableData,
156
+ pagination,
157
+ // Actions
158
+ handlePageChange,
159
+ handlePerPageChange,
160
+ handleSearchChange,
161
+ handleSortChange,
162
+ resetFilters,
163
+ setFilter,
164
+ removeFilter,
165
+ // Helpers
166
+ getNumberingColumn
167
+ };
168
+ }
169
+ export {
170
+ usePagination,
171
+ useTableNumbering
172
+ };
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@toniel/laravel-tanstack-pagination",
3
+ "version": "0.1.0",
4
+ "description": "Vue 3 composables for Laravel pagination with TanStack Query",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsup src/index.ts --format cjs,esm --dts",
20
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
21
+ "prepublishOnly": "npm run build"
22
+ },
23
+ "keywords": [
24
+ "vue",
25
+ "vue3",
26
+ "laravel",
27
+ "pagination",
28
+ "composable",
29
+ "tanstack-query"
30
+ ],
31
+ "author": "Your Name",
32
+ "license": "MIT",
33
+ "peerDependencies": {
34
+ "vue": "^3.0.0",
35
+ "@tanstack/vue-query": "^5.0.0"
36
+ },
37
+ "devDependencies": {
38
+ "@tanstack/vue-query": "^5.83.1",
39
+ "tsup": "^8.0.0",
40
+ "typescript": "^5.0.0",
41
+ "vue": "^3.5.0"
42
+ }
43
+ }