@aiaiai-pt/design-system 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/Pagination.svelte +66 -66
- package/package.json +1 -1
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
@component Pagination
|
|
3
3
|
|
|
4
4
|
Cursor-based and offset-based pagination with page size selector.
|
|
5
|
-
|
|
5
|
+
Self-contained nav controls with correct icon placement (chevron
|
|
6
|
+
leading for PREV, trailing for NEXT).
|
|
6
7
|
|
|
7
8
|
@example Cursor mode (default)
|
|
8
9
|
<Pagination
|
|
@@ -27,7 +28,6 @@
|
|
|
27
28
|
-->
|
|
28
29
|
<script>
|
|
29
30
|
import Select from './Select.svelte';
|
|
30
|
-
import Button from './Button.svelte';
|
|
31
31
|
|
|
32
32
|
let {
|
|
33
33
|
/** @type {'cursor' | 'offset'} */
|
|
@@ -72,7 +72,6 @@
|
|
|
72
72
|
|
|
73
73
|
const page_size_value = $derived(String(page_size));
|
|
74
74
|
|
|
75
|
-
/** Compute visible page numbers with ellipsis for offset mode */
|
|
76
75
|
const page_numbers = $derived(
|
|
77
76
|
mode === 'offset' && total_pages
|
|
78
77
|
? build_pages(current_page, total_pages)
|
|
@@ -103,20 +102,29 @@
|
|
|
103
102
|
return Array.from({ length: total }, (_, i) => i + 1);
|
|
104
103
|
}
|
|
105
104
|
const pages = /** @type {(number | null)[]} */ ([]);
|
|
106
|
-
// Always show first
|
|
107
105
|
pages.push(1);
|
|
108
|
-
if (current > 3) pages.push(null);
|
|
109
|
-
// Window around current
|
|
106
|
+
if (current > 3) pages.push(null);
|
|
110
107
|
const win_start = Math.max(2, current - 1);
|
|
111
108
|
const win_end = Math.min(total - 1, current + 1);
|
|
112
109
|
for (let p = win_start; p <= win_end; p++) pages.push(p);
|
|
113
|
-
if (current < total - 2) pages.push(null);
|
|
114
|
-
// Always show last
|
|
110
|
+
if (current < total - 2) pages.push(null);
|
|
115
111
|
pages.push(total);
|
|
116
112
|
return pages;
|
|
117
113
|
}
|
|
118
114
|
</script>
|
|
119
115
|
|
|
116
|
+
{#snippet chevronLeft()}
|
|
117
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
118
|
+
<path d="M10 12L6 8L10 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
119
|
+
</svg>
|
|
120
|
+
{/snippet}
|
|
121
|
+
|
|
122
|
+
{#snippet chevronRight()}
|
|
123
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
124
|
+
<path d="M6 12L10 8L6 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
125
|
+
</svg>
|
|
126
|
+
{/snippet}
|
|
127
|
+
|
|
120
128
|
<div class="pagination {className}" {...rest}>
|
|
121
129
|
{#if page_sizes && page_sizes.length > 0}
|
|
122
130
|
<div class="pagination-size">
|
|
@@ -137,51 +145,17 @@
|
|
|
137
145
|
<span class="pagination-spacer" aria-hidden="true"></span>
|
|
138
146
|
|
|
139
147
|
{#if mode === 'cursor'}
|
|
140
|
-
<
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
>
|
|
147
|
-
{#snippet icon()}
|
|
148
|
-
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
149
|
-
<path d="M10 12L6 8L10 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
150
|
-
</svg>
|
|
151
|
-
{/snippet}
|
|
152
|
-
PREV
|
|
153
|
-
</Button>
|
|
154
|
-
|
|
155
|
-
<Button
|
|
156
|
-
variant="ghost"
|
|
157
|
-
size="sm"
|
|
158
|
-
disabled={!has_next}
|
|
159
|
-
onclick={on_next}
|
|
160
|
-
aria-label="Next page"
|
|
161
|
-
>
|
|
162
|
-
NEXT
|
|
163
|
-
{#snippet icon()}
|
|
164
|
-
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
165
|
-
<path d="M6 12L10 8L6 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
166
|
-
</svg>
|
|
167
|
-
{/snippet}
|
|
168
|
-
</Button>
|
|
148
|
+
<button class="pagination-nav" disabled={!has_prev} onclick={on_prev} aria-label="Previous page">
|
|
149
|
+
{@render chevronLeft()}<span>PREV</span>
|
|
150
|
+
</button>
|
|
151
|
+
<button class="pagination-nav" disabled={!has_next} onclick={on_next} aria-label="Next page">
|
|
152
|
+
<span>NEXT</span>{@render chevronRight()}
|
|
153
|
+
</button>
|
|
169
154
|
|
|
170
155
|
{:else}
|
|
171
|
-
<
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
disabled={current_page <= 1}
|
|
175
|
-
onclick={() => on_page_change?.(current_page - 1)}
|
|
176
|
-
aria-label="Previous page"
|
|
177
|
-
>
|
|
178
|
-
{#snippet icon()}
|
|
179
|
-
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
180
|
-
<path d="M10 12L6 8L10 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
181
|
-
</svg>
|
|
182
|
-
{/snippet}
|
|
183
|
-
PREV
|
|
184
|
-
</Button>
|
|
156
|
+
<button class="pagination-nav" disabled={current_page <= 1} onclick={() => on_page_change?.(current_page - 1)} aria-label="Previous page">
|
|
157
|
+
{@render chevronLeft()}<span>PREV</span>
|
|
158
|
+
</button>
|
|
185
159
|
|
|
186
160
|
<div class="pagination-pages">
|
|
187
161
|
{#each page_numbers as p}
|
|
@@ -202,20 +176,9 @@
|
|
|
202
176
|
{/each}
|
|
203
177
|
</div>
|
|
204
178
|
|
|
205
|
-
<
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
disabled={current_page >= (total_pages ?? current_page)}
|
|
209
|
-
onclick={() => on_page_change?.(current_page + 1)}
|
|
210
|
-
aria-label="Next page"
|
|
211
|
-
>
|
|
212
|
-
NEXT
|
|
213
|
-
{#snippet icon()}
|
|
214
|
-
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
215
|
-
<path d="M6 12L10 8L6 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
216
|
-
</svg>
|
|
217
|
-
{/snippet}
|
|
218
|
-
</Button>
|
|
179
|
+
<button class="pagination-nav" disabled={current_page >= (total_pages ?? current_page)} onclick={() => on_page_change?.(current_page + 1)} aria-label="Next page">
|
|
180
|
+
<span>NEXT</span>{@render chevronRight()}
|
|
181
|
+
</button>
|
|
219
182
|
{/if}
|
|
220
183
|
</div>
|
|
221
184
|
|
|
@@ -228,7 +191,6 @@
|
|
|
228
191
|
}
|
|
229
192
|
|
|
230
193
|
.pagination-size {
|
|
231
|
-
/* Constrain size selector width */
|
|
232
194
|
width: 80px;
|
|
233
195
|
}
|
|
234
196
|
|
|
@@ -244,6 +206,44 @@
|
|
|
244
206
|
min-width: var(--space-sm);
|
|
245
207
|
}
|
|
246
208
|
|
|
209
|
+
/* ─── Nav buttons (PREV / NEXT) ─── */
|
|
210
|
+
.pagination-nav {
|
|
211
|
+
all: unset;
|
|
212
|
+
display: inline-flex;
|
|
213
|
+
align-items: center;
|
|
214
|
+
gap: var(--space-xs);
|
|
215
|
+
padding: var(--space-xs) var(--space-sm);
|
|
216
|
+
font-family: var(--type-label-font);
|
|
217
|
+
font-size: var(--type-label-size);
|
|
218
|
+
letter-spacing: var(--type-label-tracking);
|
|
219
|
+
color: var(--color-text-secondary);
|
|
220
|
+
cursor: pointer;
|
|
221
|
+
border-radius: var(--radius-sm);
|
|
222
|
+
transition: color var(--duration-instant) var(--easing-default),
|
|
223
|
+
background var(--duration-instant) var(--easing-default);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.pagination-nav:hover:not(:disabled) {
|
|
227
|
+
color: var(--color-text);
|
|
228
|
+
background: var(--color-surface-secondary);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.pagination-nav:disabled {
|
|
232
|
+
opacity: 0.4;
|
|
233
|
+
cursor: default;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.pagination-nav:focus-visible {
|
|
237
|
+
outline: var(--focus-ring-width) solid var(--focus-ring-color);
|
|
238
|
+
outline-offset: var(--focus-ring-offset);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.pagination-nav svg {
|
|
242
|
+
width: var(--icon-size-sm);
|
|
243
|
+
height: var(--icon-size-sm);
|
|
244
|
+
flex-shrink: 0;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
247
|
/* ─── Offset page numbers ─── */
|
|
248
248
|
.pagination-pages {
|
|
249
249
|
display: flex;
|