@makolabs/ripple 0.0.1-dev.56 → 0.0.1-dev.58
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/dist/index.d.ts +11 -0
- package/dist/layout/table/Table.svelte +423 -50
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -201,6 +201,8 @@ export type TableProps<T extends DataRow = any> = {
|
|
|
201
201
|
bordered?: boolean;
|
|
202
202
|
striped?: boolean;
|
|
203
203
|
pageSize?: number;
|
|
204
|
+
currentPage?: number;
|
|
205
|
+
totalItems?: number;
|
|
204
206
|
selectable?: boolean;
|
|
205
207
|
selected?: T[];
|
|
206
208
|
class?: ClassValue;
|
|
@@ -212,12 +214,21 @@ export type TableProps<T extends DataRow = any> = {
|
|
|
212
214
|
thclass?: ClassValue;
|
|
213
215
|
tdclass?: ClassValue;
|
|
214
216
|
footerclass?: ClassValue;
|
|
217
|
+
paginationclass?: ClassValue;
|
|
215
218
|
onrowclick?: (row: T, index: number) => void;
|
|
216
219
|
onsort?: (sortState: SortState) => void;
|
|
217
220
|
onselect?: (selected: T[]) => void;
|
|
221
|
+
onpagechange?: (page: number) => void;
|
|
218
222
|
rowclass?: (row: T, index: number) => ClassValue;
|
|
219
223
|
loading?: boolean;
|
|
220
224
|
expandedContent?: Snippet<[T]>;
|
|
225
|
+
pagination?: boolean;
|
|
226
|
+
showPagination?: boolean;
|
|
227
|
+
showPageSize?: boolean;
|
|
228
|
+
pageSizeOptions?: number[];
|
|
229
|
+
onpagesizechange?: (pageSize: number) => void;
|
|
230
|
+
paginationPosition?: 'top' | 'bottom' | 'both';
|
|
231
|
+
paginationTemplate?: 'simple' | 'full';
|
|
221
232
|
};
|
|
222
233
|
export type BreadcrumbItem = {
|
|
223
234
|
label: string;
|
|
@@ -9,11 +9,15 @@
|
|
|
9
9
|
bordered = true,
|
|
10
10
|
striped = false,
|
|
11
11
|
pageSize = 10,
|
|
12
|
+
currentPage: externalCurrentPage,
|
|
13
|
+
totalItems,
|
|
12
14
|
selectable = false,
|
|
13
15
|
selected = $bindable([]),
|
|
14
16
|
onrowclick,
|
|
15
17
|
onsort = () => {},
|
|
16
18
|
onselect = () => {},
|
|
19
|
+
onpagechange,
|
|
20
|
+
onpagesizechange,
|
|
17
21
|
class: classname = '',
|
|
18
22
|
wrapperclass: wrapperClass = '',
|
|
19
23
|
tableclass: tableClass = '',
|
|
@@ -23,17 +27,40 @@
|
|
|
23
27
|
thclass: thClass = '',
|
|
24
28
|
tdclass: tdClass = '',
|
|
25
29
|
footerclass: footerClass = '',
|
|
30
|
+
paginationclass: paginationClass = '',
|
|
26
31
|
rowclass = () => '',
|
|
27
32
|
loading = false,
|
|
28
|
-
expandedContent
|
|
33
|
+
expandedContent,
|
|
34
|
+
pagination = true,
|
|
35
|
+
showPagination = true,
|
|
36
|
+
showPageSize = false,
|
|
37
|
+
pageSizeOptions = [5, 10, 25, 50, 100],
|
|
38
|
+
paginationPosition = 'bottom',
|
|
39
|
+
paginationTemplate = 'full'
|
|
29
40
|
}: TableProps<any> = $props();
|
|
30
41
|
|
|
31
42
|
let sortColumn = $state('');
|
|
32
43
|
let sortDirection = $state<SortDirection>(null);
|
|
33
|
-
let
|
|
44
|
+
let internalCurrentPage = $state(externalCurrentPage || 1);
|
|
45
|
+
let internalPageSize = $state(pageSize);
|
|
34
46
|
|
|
35
|
-
//
|
|
36
|
-
|
|
47
|
+
// Use external current page if provided
|
|
48
|
+
$effect(() => {
|
|
49
|
+
if (externalCurrentPage !== undefined) {
|
|
50
|
+
internalCurrentPage = externalCurrentPage;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Pagination is automatically determined by pageSize and pagination prop
|
|
55
|
+
const showPaginationControls = $derived(
|
|
56
|
+
pagination &&
|
|
57
|
+
showPagination &&
|
|
58
|
+
(data.length > internalPageSize || totalItems > internalPageSize)
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
// Calculate total items and pages
|
|
62
|
+
const effectiveTotalItems = $derived(totalItems !== undefined ? totalItems : data.length);
|
|
63
|
+
const totalPages = $derived(Math.ceil(effectiveTotalItems / internalPageSize));
|
|
37
64
|
|
|
38
65
|
const {
|
|
39
66
|
base: baseClass,
|
|
@@ -65,13 +92,28 @@
|
|
|
65
92
|
const thClasses = $derived(cn(thBaseClass(), thClass));
|
|
66
93
|
const tdClasses = $derived(cn(tdBaseClass(), tdClass));
|
|
67
94
|
const footerClasses = $derived(cn(footerBaseClass(), footerClass));
|
|
95
|
+
const paginationClasses = $derived(cn(paginationBaseClass(), paginationClass));
|
|
68
96
|
const emptyStateClasses = $derived(emptyStateBaseClass());
|
|
69
97
|
|
|
70
98
|
// Handle pagination
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
pagination
|
|
74
|
-
|
|
99
|
+
function getPaginatedData() {
|
|
100
|
+
// If no pagination or all data fits on one page, return all data
|
|
101
|
+
if (!pagination || data.length <= internalPageSize) {
|
|
102
|
+
return data;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// If external data source might be handling pagination
|
|
106
|
+
if (totalItems !== undefined) {
|
|
107
|
+
// If data.length is less than or equal to pageSize, assume it's already paginated
|
|
108
|
+
if (data.length <= internalPageSize) {
|
|
109
|
+
return data;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Otherwise, handle pagination internally
|
|
114
|
+
const startIndex = (internalCurrentPage - 1) * internalPageSize;
|
|
115
|
+
return data.slice(startIndex, startIndex + internalPageSize);
|
|
116
|
+
}
|
|
75
117
|
|
|
76
118
|
// Handle sorting
|
|
77
119
|
function toggleSort(column: string) {
|
|
@@ -118,26 +160,262 @@
|
|
|
118
160
|
onrowclick?.(row, index);
|
|
119
161
|
}
|
|
120
162
|
|
|
163
|
+
function goToFirstPage() {
|
|
164
|
+
if (internalCurrentPage !== 1) {
|
|
165
|
+
internalCurrentPage = 1;
|
|
166
|
+
onpagechange?.(internalCurrentPage);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function goToLastPage() {
|
|
171
|
+
if (internalCurrentPage !== totalPages) {
|
|
172
|
+
internalCurrentPage = totalPages;
|
|
173
|
+
onpagechange?.(internalCurrentPage);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
121
177
|
function nextPage() {
|
|
122
|
-
if (
|
|
123
|
-
|
|
178
|
+
if (internalCurrentPage < totalPages) {
|
|
179
|
+
internalCurrentPage++;
|
|
180
|
+
onpagechange?.(internalCurrentPage);
|
|
124
181
|
}
|
|
125
182
|
}
|
|
126
183
|
|
|
127
184
|
function prevPage() {
|
|
128
|
-
if (
|
|
129
|
-
|
|
185
|
+
if (internalCurrentPage > 1) {
|
|
186
|
+
internalCurrentPage--;
|
|
187
|
+
onpagechange?.(internalCurrentPage);
|
|
130
188
|
}
|
|
131
189
|
}
|
|
132
190
|
|
|
133
191
|
function goToPage(page: number) {
|
|
134
|
-
if (page >= 1 && page <= totalPages) {
|
|
135
|
-
|
|
192
|
+
if (page >= 1 && page <= totalPages && page !== internalCurrentPage) {
|
|
193
|
+
internalCurrentPage = page;
|
|
194
|
+
onpagechange?.(internalCurrentPage);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function handlePageSizeChange(event: Event) {
|
|
199
|
+
const select = event.target as HTMLSelectElement;
|
|
200
|
+
const newPageSize = parseInt(select.value, 10);
|
|
201
|
+
internalPageSize = newPageSize;
|
|
202
|
+
|
|
203
|
+
// Adjust current page if it would exceed the new total pages
|
|
204
|
+
const newTotalPages = Math.ceil(effectiveTotalItems / newPageSize);
|
|
205
|
+
if (internalCurrentPage > newTotalPages) {
|
|
206
|
+
internalCurrentPage = newTotalPages || 1;
|
|
136
207
|
}
|
|
208
|
+
|
|
209
|
+
onpagesizechange?.(newPageSize);
|
|
210
|
+
onpagechange?.(internalCurrentPage);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function getPageNumbers(): number[] {
|
|
214
|
+
const pages: number[] = [];
|
|
215
|
+
const maxPages = 5;
|
|
216
|
+
const halfMax = Math.floor(maxPages / 2);
|
|
217
|
+
|
|
218
|
+
let start = Math.max(1, internalCurrentPage - halfMax);
|
|
219
|
+
let end = Math.min(totalPages, start + maxPages - 1);
|
|
220
|
+
|
|
221
|
+
if (end - start + 1 < maxPages) {
|
|
222
|
+
start = Math.max(1, end - maxPages + 1);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
for (let i = start; i <= end; i++) {
|
|
226
|
+
pages.push(i);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return pages;
|
|
137
230
|
}
|
|
138
231
|
</script>
|
|
139
232
|
|
|
140
233
|
<div class={baseClasses}>
|
|
234
|
+
{#if showPaginationControls && (paginationPosition === 'top' || paginationPosition === 'both')}
|
|
235
|
+
<div class={footerClasses}>
|
|
236
|
+
<div class={paginationClasses}>
|
|
237
|
+
<div class="flex items-center gap-2">
|
|
238
|
+
{#if showPageSize}
|
|
239
|
+
<div class="flex items-center gap-2">
|
|
240
|
+
<label for="table-page-size" class="text-default-500 text-sm">Show</label>
|
|
241
|
+
<select
|
|
242
|
+
id="table-page-size"
|
|
243
|
+
class="border-default-200 rounded-md border px-2 py-1 text-sm"
|
|
244
|
+
value={internalPageSize}
|
|
245
|
+
onchange={handlePageSizeChange}
|
|
246
|
+
>
|
|
247
|
+
{#each pageSizeOptions as option}
|
|
248
|
+
<option value={option}>{option}</option>
|
|
249
|
+
{/each}
|
|
250
|
+
</select>
|
|
251
|
+
<span class="text-default-500 text-sm">entries</span>
|
|
252
|
+
</div>
|
|
253
|
+
{/if}
|
|
254
|
+
<span class="text-default-500 text-sm">
|
|
255
|
+
Showing {Math.min(
|
|
256
|
+
(internalCurrentPage - 1) * internalPageSize + 1,
|
|
257
|
+
effectiveTotalItems
|
|
258
|
+
)}
|
|
259
|
+
to {Math.min(internalCurrentPage * internalPageSize, effectiveTotalItems)} of {effectiveTotalItems}
|
|
260
|
+
entries
|
|
261
|
+
</span>
|
|
262
|
+
</div>
|
|
263
|
+
|
|
264
|
+
<div class="flex items-center gap-1">
|
|
265
|
+
{#if paginationTemplate === 'full'}
|
|
266
|
+
<!-- First page button -->
|
|
267
|
+
<button
|
|
268
|
+
type="button"
|
|
269
|
+
class={cn(
|
|
270
|
+
'relative inline-flex items-center rounded-md px-2 py-1 text-sm font-medium',
|
|
271
|
+
internalCurrentPage === 1
|
|
272
|
+
? 'text-default-300 cursor-not-allowed'
|
|
273
|
+
: 'text-default-700 hover:bg-default-100'
|
|
274
|
+
)}
|
|
275
|
+
onclick={goToFirstPage}
|
|
276
|
+
disabled={internalCurrentPage === 1}
|
|
277
|
+
aria-label="First page"
|
|
278
|
+
>
|
|
279
|
+
<!-- Double Chevron Left SVG -->
|
|
280
|
+
<svg
|
|
281
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
282
|
+
width="16"
|
|
283
|
+
height="16"
|
|
284
|
+
viewBox="0 0 24 24"
|
|
285
|
+
fill="none"
|
|
286
|
+
stroke="currentColor"
|
|
287
|
+
stroke-width="2"
|
|
288
|
+
stroke-linecap="round"
|
|
289
|
+
stroke-linejoin="round"
|
|
290
|
+
class="h-4 w-4"
|
|
291
|
+
>
|
|
292
|
+
<path d="m11 17-5-5 5-5"></path>
|
|
293
|
+
<path d="m18 17-5-5 5-5"></path>
|
|
294
|
+
</svg>
|
|
295
|
+
</button>
|
|
296
|
+
{/if}
|
|
297
|
+
|
|
298
|
+
<!-- Previous page button -->
|
|
299
|
+
<button
|
|
300
|
+
type="button"
|
|
301
|
+
class={cn(
|
|
302
|
+
'relative inline-flex items-center rounded-md px-2 py-1 text-sm font-medium',
|
|
303
|
+
internalCurrentPage === 1
|
|
304
|
+
? 'text-default-300 cursor-not-allowed'
|
|
305
|
+
: 'text-default-700 hover:bg-default-100'
|
|
306
|
+
)}
|
|
307
|
+
onclick={prevPage}
|
|
308
|
+
disabled={internalCurrentPage === 1}
|
|
309
|
+
aria-label="Previous page"
|
|
310
|
+
>
|
|
311
|
+
<!-- Chevron Left SVG -->
|
|
312
|
+
<svg
|
|
313
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
314
|
+
width="16"
|
|
315
|
+
height="16"
|
|
316
|
+
viewBox="0 0 24 24"
|
|
317
|
+
fill="none"
|
|
318
|
+
stroke="currentColor"
|
|
319
|
+
stroke-width="2"
|
|
320
|
+
stroke-linecap="round"
|
|
321
|
+
stroke-linejoin="round"
|
|
322
|
+
class="h-4 w-4"
|
|
323
|
+
>
|
|
324
|
+
<path d="m15 18-6-6 6-6"></path>
|
|
325
|
+
</svg>
|
|
326
|
+
</button>
|
|
327
|
+
|
|
328
|
+
<!-- Page numbers -->
|
|
329
|
+
{#if paginationTemplate === 'full'}
|
|
330
|
+
{#each getPageNumbers() as pageNum}
|
|
331
|
+
<button
|
|
332
|
+
type="button"
|
|
333
|
+
class={cn(
|
|
334
|
+
'relative inline-flex items-center rounded-md px-3 py-1 text-sm font-medium',
|
|
335
|
+
internalCurrentPage === pageNum
|
|
336
|
+
? 'bg-primary-100 text-primary-700'
|
|
337
|
+
: 'text-default-700 hover:bg-default-100'
|
|
338
|
+
)}
|
|
339
|
+
onclick={() => goToPage(pageNum)}
|
|
340
|
+
aria-label={`Page ${pageNum}`}
|
|
341
|
+
aria-current={internalCurrentPage === pageNum ? 'page' : undefined}
|
|
342
|
+
>
|
|
343
|
+
{pageNum}
|
|
344
|
+
</button>
|
|
345
|
+
{/each}
|
|
346
|
+
{:else}
|
|
347
|
+
<span class="text-default-500 px-2 text-sm">
|
|
348
|
+
Page {internalCurrentPage} of {totalPages}
|
|
349
|
+
</span>
|
|
350
|
+
{/if}
|
|
351
|
+
|
|
352
|
+
<!-- Next page button -->
|
|
353
|
+
<button
|
|
354
|
+
type="button"
|
|
355
|
+
class={cn(
|
|
356
|
+
'relative inline-flex items-center rounded-md px-2 py-1 text-sm font-medium',
|
|
357
|
+
internalCurrentPage === totalPages
|
|
358
|
+
? 'text-default-300 cursor-not-allowed'
|
|
359
|
+
: 'text-default-700 hover:bg-default-100'
|
|
360
|
+
)}
|
|
361
|
+
onclick={nextPage}
|
|
362
|
+
disabled={internalCurrentPage === totalPages}
|
|
363
|
+
aria-label="Next page"
|
|
364
|
+
>
|
|
365
|
+
<!-- Chevron Right SVG -->
|
|
366
|
+
<svg
|
|
367
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
368
|
+
width="16"
|
|
369
|
+
height="16"
|
|
370
|
+
viewBox="0 0 24 24"
|
|
371
|
+
fill="none"
|
|
372
|
+
stroke="currentColor"
|
|
373
|
+
stroke-width="2"
|
|
374
|
+
stroke-linecap="round"
|
|
375
|
+
stroke-linejoin="round"
|
|
376
|
+
class="h-4 w-4"
|
|
377
|
+
>
|
|
378
|
+
<path d="m9 18 6-6-6-6"></path>
|
|
379
|
+
</svg>
|
|
380
|
+
</button>
|
|
381
|
+
|
|
382
|
+
{#if paginationTemplate === 'full'}
|
|
383
|
+
<!-- Last page button -->
|
|
384
|
+
<button
|
|
385
|
+
type="button"
|
|
386
|
+
class={cn(
|
|
387
|
+
'relative inline-flex items-center rounded-md px-2 py-1 text-sm font-medium',
|
|
388
|
+
internalCurrentPage === totalPages
|
|
389
|
+
? 'text-default-300 cursor-not-allowed'
|
|
390
|
+
: 'text-default-700 hover:bg-default-100'
|
|
391
|
+
)}
|
|
392
|
+
onclick={goToLastPage}
|
|
393
|
+
disabled={internalCurrentPage === totalPages}
|
|
394
|
+
aria-label="Last page"
|
|
395
|
+
>
|
|
396
|
+
<!-- Double Chevron Right SVG -->
|
|
397
|
+
<svg
|
|
398
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
399
|
+
width="16"
|
|
400
|
+
height="16"
|
|
401
|
+
viewBox="0 0 24 24"
|
|
402
|
+
fill="none"
|
|
403
|
+
stroke="currentColor"
|
|
404
|
+
stroke-width="2"
|
|
405
|
+
stroke-linecap="round"
|
|
406
|
+
stroke-linejoin="round"
|
|
407
|
+
class="h-4 w-4"
|
|
408
|
+
>
|
|
409
|
+
<path d="m13 17 5-5-5-5"></path>
|
|
410
|
+
<path d="m6 17 5-5-5-5"></path>
|
|
411
|
+
</svg>
|
|
412
|
+
</button>
|
|
413
|
+
{/if}
|
|
414
|
+
</div>
|
|
415
|
+
</div>
|
|
416
|
+
</div>
|
|
417
|
+
{/if}
|
|
418
|
+
|
|
141
419
|
<div class={wrapperClasses}>
|
|
142
420
|
<table class={tableClasses}>
|
|
143
421
|
<thead class={theadClasses}>
|
|
@@ -260,7 +538,7 @@
|
|
|
260
538
|
</div>
|
|
261
539
|
</td>
|
|
262
540
|
</tr>
|
|
263
|
-
{:else if
|
|
541
|
+
{:else if getPaginatedData().length === 0}
|
|
264
542
|
<tr>
|
|
265
543
|
<td
|
|
266
544
|
colspan={selectable ? columns.length + 1 : columns.length}
|
|
@@ -270,7 +548,7 @@
|
|
|
270
548
|
</td>
|
|
271
549
|
</tr>
|
|
272
550
|
{:else}
|
|
273
|
-
{#each
|
|
551
|
+
{#each getPaginatedData() as row, rowIndex}
|
|
274
552
|
<tr
|
|
275
553
|
class={cn(trClasses, rowclass(row, rowIndex), {
|
|
276
554
|
'bg-primary-100': selectable && isRowSelected(row),
|
|
@@ -325,91 +603,186 @@
|
|
|
325
603
|
</table>
|
|
326
604
|
</div>
|
|
327
605
|
|
|
328
|
-
{#if
|
|
606
|
+
{#if showPaginationControls && (paginationPosition === 'bottom' || paginationPosition === 'both')}
|
|
329
607
|
<div class={footerClasses}>
|
|
330
|
-
<div class={
|
|
608
|
+
<div class={paginationClasses}>
|
|
331
609
|
<div class="flex items-center gap-2">
|
|
610
|
+
{#if showPageSize}
|
|
611
|
+
<div class="flex items-center gap-2">
|
|
612
|
+
<label for="table-page-size-bottom" class="text-default-500 text-sm">Show</label>
|
|
613
|
+
<select
|
|
614
|
+
id="table-page-size-bottom"
|
|
615
|
+
class="border-default-200 rounded-md border px-2 py-1 text-sm"
|
|
616
|
+
value={internalPageSize}
|
|
617
|
+
onchange={handlePageSizeChange}
|
|
618
|
+
>
|
|
619
|
+
{#each pageSizeOptions as option}
|
|
620
|
+
<option value={option}>{option}</option>
|
|
621
|
+
{/each}
|
|
622
|
+
</select>
|
|
623
|
+
<span class="text-default-500 text-sm">entries</span>
|
|
624
|
+
</div>
|
|
625
|
+
{/if}
|
|
332
626
|
<span class="text-default-500 text-sm">
|
|
333
|
-
Showing {Math.min(
|
|
334
|
-
|
|
627
|
+
Showing {Math.min(
|
|
628
|
+
(internalCurrentPage - 1) * internalPageSize + 1,
|
|
629
|
+
effectiveTotalItems
|
|
630
|
+
)}
|
|
631
|
+
to {Math.min(internalCurrentPage * internalPageSize, effectiveTotalItems)} of {effectiveTotalItems}
|
|
632
|
+
entries
|
|
335
633
|
</span>
|
|
336
634
|
</div>
|
|
337
635
|
|
|
338
636
|
<div class="flex items-center gap-1">
|
|
637
|
+
{#if paginationTemplate === 'full'}
|
|
638
|
+
<!-- First page button -->
|
|
639
|
+
<button
|
|
640
|
+
type="button"
|
|
641
|
+
class={cn(
|
|
642
|
+
'relative inline-flex items-center rounded-md px-2 py-1 text-sm font-medium',
|
|
643
|
+
internalCurrentPage === 1
|
|
644
|
+
? 'text-default-300 cursor-not-allowed'
|
|
645
|
+
: 'text-default-700 hover:bg-default-100'
|
|
646
|
+
)}
|
|
647
|
+
onclick={goToFirstPage}
|
|
648
|
+
disabled={internalCurrentPage === 1}
|
|
649
|
+
aria-label="First page"
|
|
650
|
+
>
|
|
651
|
+
<!-- Double Chevron Left SVG -->
|
|
652
|
+
<svg
|
|
653
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
654
|
+
width="16"
|
|
655
|
+
height="16"
|
|
656
|
+
viewBox="0 0 24 24"
|
|
657
|
+
fill="none"
|
|
658
|
+
stroke="currentColor"
|
|
659
|
+
stroke-width="2"
|
|
660
|
+
stroke-linecap="round"
|
|
661
|
+
stroke-linejoin="round"
|
|
662
|
+
class="h-4 w-4"
|
|
663
|
+
>
|
|
664
|
+
<path d="m11 17-5-5 5-5"></path>
|
|
665
|
+
<path d="m18 17-5-5 5-5"></path>
|
|
666
|
+
</svg>
|
|
667
|
+
</button>
|
|
668
|
+
{/if}
|
|
669
|
+
|
|
670
|
+
<!-- Previous page button -->
|
|
339
671
|
<button
|
|
340
672
|
type="button"
|
|
341
673
|
class={cn(
|
|
342
674
|
'relative inline-flex items-center rounded-md px-2 py-1 text-sm font-medium',
|
|
343
|
-
|
|
675
|
+
internalCurrentPage === 1
|
|
344
676
|
? 'text-default-300 cursor-not-allowed'
|
|
345
677
|
: 'text-default-700 hover:bg-default-100'
|
|
346
678
|
)}
|
|
347
679
|
onclick={prevPage}
|
|
348
|
-
disabled={
|
|
680
|
+
disabled={internalCurrentPage === 1}
|
|
349
681
|
aria-label="Previous page"
|
|
350
682
|
>
|
|
683
|
+
<!-- Chevron Left SVG -->
|
|
351
684
|
<svg
|
|
352
685
|
xmlns="http://www.w3.org/2000/svg"
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
686
|
+
width="16"
|
|
687
|
+
height="16"
|
|
688
|
+
viewBox="0 0 24 24"
|
|
689
|
+
fill="none"
|
|
690
|
+
stroke="currentColor"
|
|
691
|
+
stroke-width="2"
|
|
692
|
+
stroke-linecap="round"
|
|
693
|
+
stroke-linejoin="round"
|
|
694
|
+
class="h-4 w-4"
|
|
356
695
|
>
|
|
357
|
-
<path
|
|
358
|
-
d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z"
|
|
359
|
-
/>
|
|
696
|
+
<path d="m15 18-6-6 6-6"></path>
|
|
360
697
|
</svg>
|
|
361
698
|
</button>
|
|
362
699
|
|
|
363
|
-
<!--
|
|
364
|
-
{#
|
|
365
|
-
{
|
|
366
|
-
currentPage <= 3
|
|
367
|
-
? i + 1
|
|
368
|
-
: currentPage >= totalPages - 2
|
|
369
|
-
? totalPages - 4 + i
|
|
370
|
-
: currentPage - 2 + i}
|
|
371
|
-
|
|
372
|
-
{#if pageNum > 0 && pageNum <= totalPages}
|
|
700
|
+
<!-- Page numbers -->
|
|
701
|
+
{#if paginationTemplate === 'full'}
|
|
702
|
+
{#each getPageNumbers() as pageNum}
|
|
373
703
|
<button
|
|
374
704
|
type="button"
|
|
375
705
|
class={cn(
|
|
376
706
|
'relative inline-flex items-center rounded-md px-3 py-1 text-sm font-medium',
|
|
377
|
-
|
|
707
|
+
internalCurrentPage === pageNum
|
|
378
708
|
? 'bg-primary-100 text-primary-700'
|
|
379
709
|
: 'text-default-700 hover:bg-default-100'
|
|
380
710
|
)}
|
|
381
711
|
onclick={() => goToPage(pageNum)}
|
|
382
712
|
aria-label={`Page ${pageNum}`}
|
|
383
|
-
aria-current={
|
|
713
|
+
aria-current={internalCurrentPage === pageNum ? 'page' : undefined}
|
|
384
714
|
>
|
|
385
715
|
{pageNum}
|
|
386
716
|
</button>
|
|
387
|
-
{/
|
|
388
|
-
{
|
|
717
|
+
{/each}
|
|
718
|
+
{:else}
|
|
719
|
+
<span class="text-default-500 px-2 text-sm">
|
|
720
|
+
Page {internalCurrentPage} of {totalPages}
|
|
721
|
+
</span>
|
|
722
|
+
{/if}
|
|
389
723
|
|
|
724
|
+
<!-- Next page button -->
|
|
390
725
|
<button
|
|
391
726
|
type="button"
|
|
392
727
|
class={cn(
|
|
393
728
|
'relative inline-flex items-center rounded-md px-2 py-1 text-sm font-medium',
|
|
394
|
-
|
|
729
|
+
internalCurrentPage === totalPages
|
|
395
730
|
? 'text-default-300 cursor-not-allowed'
|
|
396
731
|
: 'text-default-700 hover:bg-default-100'
|
|
397
732
|
)}
|
|
398
733
|
onclick={nextPage}
|
|
399
|
-
disabled={
|
|
734
|
+
disabled={internalCurrentPage === totalPages}
|
|
400
735
|
aria-label="Next page"
|
|
401
736
|
>
|
|
737
|
+
<!-- Chevron Right SVG -->
|
|
402
738
|
<svg
|
|
403
739
|
xmlns="http://www.w3.org/2000/svg"
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
740
|
+
width="16"
|
|
741
|
+
height="16"
|
|
742
|
+
viewBox="0 0 24 24"
|
|
743
|
+
fill="none"
|
|
744
|
+
stroke="currentColor"
|
|
745
|
+
stroke-width="2"
|
|
746
|
+
stroke-linecap="round"
|
|
747
|
+
stroke-linejoin="round"
|
|
748
|
+
class="h-4 w-4"
|
|
407
749
|
>
|
|
408
|
-
<path
|
|
409
|
-
d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z"
|
|
410
|
-
/>
|
|
750
|
+
<path d="m9 18 6-6-6-6"></path>
|
|
411
751
|
</svg>
|
|
412
752
|
</button>
|
|
753
|
+
|
|
754
|
+
{#if paginationTemplate === 'full'}
|
|
755
|
+
<!-- Last page button -->
|
|
756
|
+
<button
|
|
757
|
+
type="button"
|
|
758
|
+
class={cn(
|
|
759
|
+
'relative inline-flex items-center rounded-md px-2 py-1 text-sm font-medium',
|
|
760
|
+
internalCurrentPage === totalPages
|
|
761
|
+
? 'text-default-300 cursor-not-allowed'
|
|
762
|
+
: 'text-default-700 hover:bg-default-100'
|
|
763
|
+
)}
|
|
764
|
+
onclick={goToLastPage}
|
|
765
|
+
disabled={internalCurrentPage === totalPages}
|
|
766
|
+
aria-label="Last page"
|
|
767
|
+
>
|
|
768
|
+
<!-- Double Chevron Right SVG -->
|
|
769
|
+
<svg
|
|
770
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
771
|
+
width="16"
|
|
772
|
+
height="16"
|
|
773
|
+
viewBox="0 0 24 24"
|
|
774
|
+
fill="none"
|
|
775
|
+
stroke="currentColor"
|
|
776
|
+
stroke-width="2"
|
|
777
|
+
stroke-linecap="round"
|
|
778
|
+
stroke-linejoin="round"
|
|
779
|
+
class="h-4 w-4"
|
|
780
|
+
>
|
|
781
|
+
<path d="m13 17 5-5-5-5"></path>
|
|
782
|
+
<path d="m6 17 5-5-5-5"></path>
|
|
783
|
+
</svg>
|
|
784
|
+
</button>
|
|
785
|
+
{/if}
|
|
413
786
|
</div>
|
|
414
787
|
</div>
|
|
415
788
|
</div>
|