@ttdk-design-system/library-react 0.0.0-stage → 1.0.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/AI_GUIDE.md +6518 -0
- package/README.md +106 -2
- package/llms.txt +6518 -0
- package/package.json +1099 -4
- package/src/core/index.ts +2 -0
- package/src/core/tailwind-preset.cjs +62 -0
- package/src/core/tailwind-preset.ts +85 -0
- package/src/core/theme/tokens.css +663 -0
- package/src/core/types.ts +836 -0
- package/src/index.ts +17 -0
- package/src/tailwind-preset.cjs +62 -0
- package/src/tailwind-preset.ts +85 -0
- package/src/types.ts +1 -0
- package/src/web/accordion/AI_GUIDE.md +149 -0
- package/src/web/accordion/accordion.css +1 -0
- package/src/web/accordion/accordion.tsx +430 -0
- package/src/web/accordion/index.ts +3 -0
- package/src/web/accordion/manifest.json +351 -0
- package/src/web/alert/AI_GUIDE.md +139 -0
- package/src/web/alert/alert.css +1 -0
- package/src/web/alert/alert.tsx +318 -0
- package/src/web/alert/index.ts +3 -0
- package/src/web/alert/manifest.json +240 -0
- package/src/web/avatar/AI_GUIDE.md +118 -0
- package/src/web/avatar/avatar.css +1 -0
- package/src/web/avatar/avatar.tsx +233 -0
- package/src/web/avatar/index.ts +3 -0
- package/src/web/avatar/manifest.json +195 -0
- package/src/web/badge/AI_GUIDE.md +94 -0
- package/src/web/badge/badge.css +1 -0
- package/src/web/badge/badge.tsx +140 -0
- package/src/web/badge/index.ts +2 -0
- package/src/web/badge/manifest.json +141 -0
- package/src/web/banner/AI_GUIDE.md +130 -0
- package/src/web/banner/banner.css +1 -0
- package/src/web/banner/banner.tsx +334 -0
- package/src/web/banner/index.ts +3 -0
- package/src/web/banner/manifest.json +240 -0
- package/src/web/breadcrumb/AI_GUIDE.md +120 -0
- package/src/web/breadcrumb/breadcrumb.css +1 -0
- package/src/web/breadcrumb/breadcrumb.tsx +306 -0
- package/src/web/breadcrumb/index.ts +3 -0
- package/src/web/breadcrumb/manifest.json +225 -0
- package/src/web/button/AI_GUIDE.md +121 -0
- package/src/web/button/button.css +1 -0
- package/src/web/button/button.tsx +287 -0
- package/src/web/button/index.ts +2 -0
- package/src/web/button/manifest.json +177 -0
- package/src/web/calendar/AI_GUIDE.md +151 -0
- package/src/web/calendar/calendar.css +1 -0
- package/src/web/calendar/calendar.tsx +1611 -0
- package/src/web/calendar/index.ts +3 -0
- package/src/web/calendar/manifest.json +470 -0
- package/src/web/card/AI_GUIDE.md +133 -0
- package/src/web/card/card.css +1 -0
- package/src/web/card/card.tsx +408 -0
- package/src/web/card/index.ts +4 -0
- package/src/web/card/manifest.json +357 -0
- package/src/web/checkbox/AI_GUIDE.md +146 -0
- package/src/web/checkbox/checkbox.css +1 -0
- package/src/web/checkbox/checkbox.tsx +307 -0
- package/src/web/checkbox/index.ts +2 -0
- package/src/web/checkbox/manifest.json +294 -0
- package/src/web/chip/AI_GUIDE.md +186 -0
- package/src/web/chip/chip.css +1 -0
- package/src/web/chip/chip.tsx +230 -0
- package/src/web/chip/index.ts +2 -0
- package/src/web/chip/manifest.json +186 -0
- package/src/web/dropdown/AI_GUIDE.md +167 -0
- package/src/web/dropdown/dropdown.css +1 -0
- package/src/web/dropdown/dropdown.tsx +1274 -0
- package/src/web/dropdown/index.ts +3 -0
- package/src/web/dropdown/manifest.json +576 -0
- package/src/web/flex/AI_GUIDE.md +113 -0
- package/src/web/flex/flex-item.tsx +97 -0
- package/src/web/flex/flex.css +1 -0
- package/src/web/flex/flex.tsx +108 -0
- package/src/web/flex/index.ts +5 -0
- package/src/web/flex/manifest.json +162 -0
- package/src/web/form/index.ts +7 -0
- package/src/web/grid/AI_GUIDE.md +112 -0
- package/src/web/grid/grid-item.tsx +112 -0
- package/src/web/grid/grid.css +1 -0
- package/src/web/grid/grid.tsx +99 -0
- package/src/web/grid/index.ts +5 -0
- package/src/web/grid/manifest.json +153 -0
- package/src/web/index.ts +86 -0
- package/src/web/input/AI_GUIDE.md +159 -0
- package/src/web/input/index.ts +3 -0
- package/src/web/input/input.css +1 -0
- package/src/web/input/input.tsx +537 -0
- package/src/web/input/manifest.json +465 -0
- package/src/web/input-number/AI_GUIDE.md +164 -0
- package/src/web/input-number/index.ts +3 -0
- package/src/web/input-number/input-number.css +1 -0
- package/src/web/input-number/input-number.tsx +1193 -0
- package/src/web/input-number/manifest.json +575 -0
- package/src/web/modal/AI_GUIDE.md +171 -0
- package/src/web/modal/index.ts +3 -0
- package/src/web/modal/manifest.json +375 -0
- package/src/web/modal/modal.css +1 -0
- package/src/web/modal/modal.tsx +571 -0
- package/src/web/pagination/AI_GUIDE.md +148 -0
- package/src/web/pagination/index.ts +21 -0
- package/src/web/pagination/manifest.json +432 -0
- package/src/web/pagination/pagination-content.tsx +45 -0
- package/src/web/pagination/pagination-ellipsis.tsx +54 -0
- package/src/web/pagination/pagination-first.tsx +155 -0
- package/src/web/pagination/pagination-item.tsx +45 -0
- package/src/web/pagination/pagination-last.tsx +155 -0
- package/src/web/pagination/pagination-link.tsx +121 -0
- package/src/web/pagination/pagination-next.tsx +158 -0
- package/src/web/pagination/pagination-previous.tsx +158 -0
- package/src/web/pagination/pagination.css +1 -0
- package/src/web/pagination/pagination.tsx +687 -0
- package/src/web/popover/AI_GUIDE.md +163 -0
- package/src/web/popover/index.ts +3 -0
- package/src/web/popover/manifest.json +396 -0
- package/src/web/popover/popover.css +1 -0
- package/src/web/popover/popover.tsx +702 -0
- package/src/web/radio/AI_GUIDE.md +155 -0
- package/src/web/radio/index.ts +2 -0
- package/src/web/radio/manifest.json +294 -0
- package/src/web/radio/radio.css +1 -0
- package/src/web/radio/radio.tsx +290 -0
- package/src/web/selectbox/AI_GUIDE.md +216 -0
- package/src/web/selectbox/index.ts +3 -0
- package/src/web/selectbox/manifest.json +477 -0
- package/src/web/selectbox/selectbox.css +1 -0
- package/src/web/selectbox/selectbox.tsx +1048 -0
- package/src/web/sonner/AI_GUIDE.md +98 -0
- package/src/web/sonner/index.ts +114 -0
- package/src/web/sonner/manifest.json +132 -0
- package/src/web/sonner/sonner.css +1 -0
- package/src/web/sonner/sonner.tsx +177 -0
- package/src/web/table/AI_GUIDE.md +145 -0
- package/src/web/table/index.ts +35 -0
- package/src/web/table/manifest.json +168 -0
- package/src/web/table/table-body.tsx +45 -0
- package/src/web/table/table-caption.tsx +45 -0
- package/src/web/table/table-cell.tsx +74 -0
- package/src/web/table/table-empty.tsx +108 -0
- package/src/web/table/table-footer.tsx +45 -0
- package/src/web/table/table-head.tsx +80 -0
- package/src/web/table/table-header.tsx +45 -0
- package/src/web/table/table-row.tsx +69 -0
- package/src/web/table/table.css +1 -0
- package/src/web/table/table.tsx +305 -0
- package/src/web/tabs/AI_GUIDE.md +150 -0
- package/src/web/tabs/index.ts +3 -0
- package/src/web/tabs/manifest.json +315 -0
- package/src/web/tabs/tabs.css +1 -0
- package/src/web/tabs/tabs.tsx +332 -0
- package/src/web/text/AI_GUIDE.md +129 -0
- package/src/web/text/index.ts +3 -0
- package/src/web/text/manifest.json +195 -0
- package/src/web/text/text.css +1 -0
- package/src/web/text/text.tsx +689 -0
- package/src/web/textarea/AI_GUIDE.md +141 -0
- package/src/web/textarea/index.ts +3 -0
- package/src/web/textarea/manifest.json +438 -0
- package/src/web/textarea/textarea.css +1 -0
- package/src/web/textarea/textarea.tsx +467 -0
- package/src/web/tooltip/AI_GUIDE.md +110 -0
- package/src/web/tooltip/index.ts +3 -0
- package/src/web/tooltip/manifest.json +222 -0
- package/src/web/tooltip/tooltip.css +1 -0
- package/src/web/tooltip/tooltip.tsx +423 -0
- package/src/webview/bottomsheet/AI_GUIDE.md +141 -0
- package/src/webview/bottomsheet/bottomsheet.css +1 -0
- package/src/webview/bottomsheet/bottomsheet.tsx +603 -0
- package/src/webview/bottomsheet/index.ts +4 -0
- package/src/webview/bottomsheet/manifest.json +377 -0
- package/src/webview/button/AI_GUIDE.md +79 -0
- package/src/webview/button/button-ios.css +1 -0
- package/src/webview/button/button-ios.tsx +138 -0
- package/src/webview/button/button-material.css +1 -0
- package/src/webview/button/button-material.tsx +138 -0
- package/src/webview/button/index.ts +7 -0
- package/src/webview/button/manifest.json +148 -0
- package/src/webview/index.ts +7 -0
- package/tailwind-preset.cjs +62 -0
- package/tailwind-preset.js +62 -0
- package/ttdk-manifest.json +10188 -0
|
@@ -0,0 +1,687 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
|
|
4
|
+
export type PaginationUiProps = UiProps;
|
|
5
|
+
export interface PaginationPageItem {
|
|
6
|
+
type: "page" | "ellipsis";
|
|
7
|
+
value: number | string;
|
|
8
|
+
key: string;
|
|
9
|
+
}
|
|
10
|
+
export interface PaginationProps {
|
|
11
|
+
/**
|
|
12
|
+
* Nomor halaman saat ini (1-indexed).
|
|
13
|
+
* @default 1
|
|
14
|
+
*/
|
|
15
|
+
page?: number;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Jumlah total halaman maksimum (alias untuk totalPages).
|
|
19
|
+
* @default 1
|
|
20
|
+
*/
|
|
21
|
+
maxPages?: number;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Jumlah total halaman (alias maxPages).
|
|
25
|
+
* @default 1
|
|
26
|
+
*/
|
|
27
|
+
totalPages?: number;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Jumlah baris/item data per halaman (page size).
|
|
31
|
+
* @default 10
|
|
32
|
+
*/
|
|
33
|
+
limit?: number;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Callback saat jumlah baris per halaman diubah via select box.
|
|
37
|
+
*/
|
|
38
|
+
onLimitChange?: (limit: number) => void;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Pilihan angka baris per halaman pada select box.
|
|
42
|
+
* @default [10, 20, 50, 100]
|
|
43
|
+
*/
|
|
44
|
+
limitOptions?: number[];
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Menentukan apakah navigasi ke halaman sebelumnya diizinkan (false = tombol Previous dinonaktifkan).
|
|
48
|
+
* @default false
|
|
49
|
+
*/
|
|
50
|
+
canPrevPage?: boolean;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Menentukan apakah navigasi ke halaman berikutnya diizinkan (false = tombol Next dinonaktifkan).
|
|
54
|
+
* @default false
|
|
55
|
+
*/
|
|
56
|
+
canNextPage?: boolean;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Callback saat tombol First Page (halaman pertama) diklik.
|
|
60
|
+
*/
|
|
61
|
+
onFirstPage?: () => void;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Callback saat tombol Previous Page (halaman sebelumnya) diklik.
|
|
65
|
+
*/
|
|
66
|
+
onPrevPage?: () => void;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Callback saat tombol Next Page (halaman selanjutnya) diklik.
|
|
70
|
+
*/
|
|
71
|
+
onNextPage?: () => void;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Callback saat tombol Last Page (halaman terakhir) diklik.
|
|
75
|
+
*/
|
|
76
|
+
onLastPage?: () => void;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Callback saat nomor halaman tertentu diklik.
|
|
80
|
+
*/
|
|
81
|
+
onPageChange?: (page: number) => void;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Jumlah tetangga nomor halaman di samping kiri dan kanan halaman aktif.
|
|
85
|
+
* @default 1
|
|
86
|
+
*/
|
|
87
|
+
siblingCount?: number;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Menampilkan tombol First (<<) dan Last (>>).
|
|
91
|
+
* @default false
|
|
92
|
+
*/
|
|
93
|
+
showEdges?: boolean;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Menampilkan nomor halaman terpaginasi (1, 2, 3...).
|
|
97
|
+
* @default true
|
|
98
|
+
*/
|
|
99
|
+
showPageNumbers?: boolean;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Skala ukuran pagination:
|
|
103
|
+
* - `'sm'`: 28px
|
|
104
|
+
* - `'md'`: 36px (standar)
|
|
105
|
+
* - `'lg'`: 44px
|
|
106
|
+
* @default 'md'
|
|
107
|
+
*/
|
|
108
|
+
size?: "sm" | "md" | "lg";
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Inline CSS style object native.
|
|
112
|
+
*/
|
|
113
|
+
style?: React.CSSProperties;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Kustomisasi visual granular root kontainer pagination (UiProps).
|
|
117
|
+
*/
|
|
118
|
+
ui?: UiProps;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Style kustom untuk kontainer daftar pagination content (ul.ttdk-pagination-content).
|
|
122
|
+
*/
|
|
123
|
+
contentStyle?: UiProps;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Class CSS kustom untuk kontainer daftar pagination content.
|
|
127
|
+
*/
|
|
128
|
+
contentClass?: string;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Style kustom untuk tombol link nomor halaman / navigasi.
|
|
132
|
+
*/
|
|
133
|
+
linkStyle?: UiProps;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Class CSS kustom untuk tombol link nomor halaman / navigasi.
|
|
137
|
+
*/
|
|
138
|
+
linkClass?: string;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Style kustom untuk tombol nomor halaman saat aktif.
|
|
142
|
+
*/
|
|
143
|
+
activeLinkStyle?: UiProps;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Class CSS kustom untuk tombol nomor halaman saat aktif.
|
|
147
|
+
*/
|
|
148
|
+
activeLinkClass?: string;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Style kustom untuk kontainer baris per halaman (limit).
|
|
152
|
+
*/
|
|
153
|
+
limitStyle?: UiProps;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Class CSS kustom untuk kontainer baris per halaman (limit).
|
|
157
|
+
*/
|
|
158
|
+
limitClass?: string;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Style kustom untuk elemen Selectbox baris per halaman (limit).
|
|
162
|
+
*/
|
|
163
|
+
limitSelectStyle?: UiProps;
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Slot kustom untuk menggantikan elemen limit selector bawaan.
|
|
167
|
+
*/
|
|
168
|
+
limitSlot?: any;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Menentukan apakah kontrol baris per halaman (limit selectbox) ditampilkan.
|
|
172
|
+
* Jika tidak disetel, otomatis mengikuti keberadaan callback onLimitChange.
|
|
173
|
+
*/
|
|
174
|
+
showLimit?: boolean;
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Menentukan apakah teks label 'Baris per halaman:' ditampilkan di samping selectbox limit.
|
|
178
|
+
* @default true
|
|
179
|
+
*/
|
|
180
|
+
showLimitLabel?: boolean;
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Teks label untuk opsi baris per halaman.
|
|
184
|
+
* @default 'Baris per halaman:'
|
|
185
|
+
*/
|
|
186
|
+
limitLabel?: string;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Ikon kustom untuk tombol halaman pertama (first page, menggantikan <<).
|
|
190
|
+
*/
|
|
191
|
+
firstIcon?: any;
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Ikon kustom untuk tombol halaman sebelumnya (previous page, menggantikan <).
|
|
195
|
+
*/
|
|
196
|
+
prevIcon?: any;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Ikon kustom untuk tombol halaman selanjutnya (next page, menggantikan >).
|
|
200
|
+
*/
|
|
201
|
+
nextIcon?: any;
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Ikon kustom untuk tombol halaman terakhir (last page, menggantikan >>).
|
|
205
|
+
*/
|
|
206
|
+
lastIcon?: any;
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Ikon kustom untuk separator elipsis (menggantikan ...).
|
|
210
|
+
*/
|
|
211
|
+
ellipsisIcon?: any;
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Label teks tombol Previous.
|
|
215
|
+
* @default 'Previous'
|
|
216
|
+
*/
|
|
217
|
+
prevText?: string;
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Label teks tombol Next.
|
|
221
|
+
* @default 'Next'
|
|
222
|
+
*/
|
|
223
|
+
nextText?: string;
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Mode hanya menampilkan ikon pada tombol Previous dan Next tanpa teks label.
|
|
227
|
+
* @default false
|
|
228
|
+
*/
|
|
229
|
+
iconOnly?: boolean;
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Class CSS kustom.
|
|
233
|
+
*/
|
|
234
|
+
className?: string;
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Konten kustom atau subkomponen compound (PaginationContent, PaginationItem, dll).
|
|
238
|
+
*/
|
|
239
|
+
children?: any;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Komponen Pagination navigasi halaman dengan dukungan Compound API (ala Shadcn UI) dan Props-driven mode.
|
|
244
|
+
*/
|
|
245
|
+
|
|
246
|
+
import { buildUiVars, UiProps } from "../../core/types";
|
|
247
|
+
import Selectbox from "../selectbox/selectbox";
|
|
248
|
+
|
|
249
|
+
function Pagination(props: PaginationProps) {
|
|
250
|
+
function getCurrentPage() {
|
|
251
|
+
return props.page !== undefined ? props.page : 1;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function getTotalPages() {
|
|
255
|
+
if (props.maxPages !== undefined) return props.maxPages;
|
|
256
|
+
if (props.totalPages !== undefined) return props.totalPages;
|
|
257
|
+
return 1;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function getCanPrev() {
|
|
261
|
+
if (props.canPrevPage !== undefined) return props.canPrevPage;
|
|
262
|
+
return getCurrentPage() > 1;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function getCanNext() {
|
|
266
|
+
if (props.canNextPage !== undefined) return props.canNextPage;
|
|
267
|
+
return getCurrentPage() < getTotalPages();
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function getShouldShowLimit() {
|
|
271
|
+
if (props.showLimit !== undefined) {
|
|
272
|
+
return Boolean(props.showLimit);
|
|
273
|
+
}
|
|
274
|
+
return Boolean(props.onLimitChange);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function getLimitOptions() {
|
|
278
|
+
const opts = props.limitOptions || [10, 20, 50, 100];
|
|
279
|
+
return opts.map((opt: number) => ({
|
|
280
|
+
label: String(opt),
|
|
281
|
+
value: opt,
|
|
282
|
+
}));
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function getPageRange() {
|
|
286
|
+
const total = getTotalPages();
|
|
287
|
+
const current = getCurrentPage();
|
|
288
|
+
const sibling = props.siblingCount !== undefined ? props.siblingCount : 1;
|
|
289
|
+
if (total <= 1) {
|
|
290
|
+
return [
|
|
291
|
+
{
|
|
292
|
+
type: "page",
|
|
293
|
+
value: 1,
|
|
294
|
+
key: "page-1",
|
|
295
|
+
},
|
|
296
|
+
];
|
|
297
|
+
}
|
|
298
|
+
const totalPageNumbers = sibling * 2 + 5;
|
|
299
|
+
if (total <= totalPageNumbers) {
|
|
300
|
+
const pages: PaginationPageItem[] = [];
|
|
301
|
+
for (let i = 1; i <= total; i++) {
|
|
302
|
+
pages.push({
|
|
303
|
+
type: "page",
|
|
304
|
+
value: i,
|
|
305
|
+
key: `page-${i}`,
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
return pages;
|
|
309
|
+
}
|
|
310
|
+
const leftSiblingIndex = Math.max(current - sibling, 1);
|
|
311
|
+
const rightSiblingIndex = Math.min(current + sibling, total);
|
|
312
|
+
const shouldShowLeftDots = leftSiblingIndex > 2;
|
|
313
|
+
const shouldShowRightDots = rightSiblingIndex < total - 1;
|
|
314
|
+
if (!shouldShowLeftDots && shouldShowRightDots) {
|
|
315
|
+
const leftItemCount = 3 + 2 * sibling;
|
|
316
|
+
const pages: PaginationPageItem[] = [];
|
|
317
|
+
for (let i = 1; i <= leftItemCount; i++) {
|
|
318
|
+
pages.push({
|
|
319
|
+
type: "page",
|
|
320
|
+
value: i,
|
|
321
|
+
key: `page-${i}`,
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
pages.push({
|
|
325
|
+
type: "ellipsis",
|
|
326
|
+
value: "...",
|
|
327
|
+
key: "ellipsis-right",
|
|
328
|
+
});
|
|
329
|
+
pages.push({
|
|
330
|
+
type: "page",
|
|
331
|
+
value: total,
|
|
332
|
+
key: `page-${total}`,
|
|
333
|
+
});
|
|
334
|
+
return pages;
|
|
335
|
+
}
|
|
336
|
+
if (shouldShowLeftDots && !shouldShowRightDots) {
|
|
337
|
+
const rightItemCount = 3 + 2 * sibling;
|
|
338
|
+
const pages: PaginationPageItem[] = [
|
|
339
|
+
{
|
|
340
|
+
type: "page",
|
|
341
|
+
value: 1,
|
|
342
|
+
key: "page-1",
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
type: "ellipsis",
|
|
346
|
+
value: "...",
|
|
347
|
+
key: "ellipsis-left",
|
|
348
|
+
},
|
|
349
|
+
];
|
|
350
|
+
for (let i = total - rightItemCount + 1; i <= total; i++) {
|
|
351
|
+
pages.push({
|
|
352
|
+
type: "page",
|
|
353
|
+
value: i,
|
|
354
|
+
key: `page-${i}`,
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
return pages;
|
|
358
|
+
}
|
|
359
|
+
const pages: PaginationPageItem[] = [
|
|
360
|
+
{
|
|
361
|
+
type: "page",
|
|
362
|
+
value: 1,
|
|
363
|
+
key: "page-1",
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
type: "ellipsis",
|
|
367
|
+
value: "...",
|
|
368
|
+
key: "ellipsis-left",
|
|
369
|
+
},
|
|
370
|
+
];
|
|
371
|
+
for (let i = leftSiblingIndex; i <= rightSiblingIndex; i++) {
|
|
372
|
+
pages.push({
|
|
373
|
+
type: "page",
|
|
374
|
+
value: i,
|
|
375
|
+
key: `page-${i}`,
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
pages.push({
|
|
379
|
+
type: "ellipsis",
|
|
380
|
+
value: "...",
|
|
381
|
+
key: "ellipsis-right",
|
|
382
|
+
});
|
|
383
|
+
pages.push({
|
|
384
|
+
type: "page",
|
|
385
|
+
value: total,
|
|
386
|
+
key: `page-${total}`,
|
|
387
|
+
});
|
|
388
|
+
return pages;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
function handleLimitChange(val: any) {
|
|
392
|
+
if (props.onLimitChange) {
|
|
393
|
+
props.onLimitChange(Number(val));
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
return (
|
|
398
|
+
<nav
|
|
399
|
+
role="navigation"
|
|
400
|
+
aria-label="pagination"
|
|
401
|
+
className={`ttdk-pagination ${props.className || ""}`.trim()}
|
|
402
|
+
data-size={props.size || "md"}
|
|
403
|
+
style={{
|
|
404
|
+
...buildUiVars(props.ui),
|
|
405
|
+
...((props as any)["style"] || {}),
|
|
406
|
+
...props.style,
|
|
407
|
+
}}
|
|
408
|
+
>
|
|
409
|
+
{props.children ? <>{props.children}</> : null}
|
|
410
|
+
{!props.children ? (
|
|
411
|
+
<div className="ttdk-pagination-auto-wrapper">
|
|
412
|
+
{getShouldShowLimit() ? (
|
|
413
|
+
<div
|
|
414
|
+
className={`ttdk-pagination-limit ${
|
|
415
|
+
props.limitClass || ""
|
|
416
|
+
}`.trim()}
|
|
417
|
+
style={{
|
|
418
|
+
...buildUiVars(props.limitStyle),
|
|
419
|
+
}}
|
|
420
|
+
>
|
|
421
|
+
{props.showLimitLabel !== false ? (
|
|
422
|
+
<span className="ttdk-pagination-limit-label">
|
|
423
|
+
{props.limitLabel || "Baris per halaman:"}
|
|
424
|
+
</span>
|
|
425
|
+
) : null}
|
|
426
|
+
{props.limitSlot ? <>{props.limitSlot}</> : null}
|
|
427
|
+
{!props.limitSlot ? (
|
|
428
|
+
<Selectbox
|
|
429
|
+
size={props.size === "lg" ? "md" : "sm"}
|
|
430
|
+
value={props.limit || 10}
|
|
431
|
+
options={getLimitOptions()}
|
|
432
|
+
onChange={(val) => handleLimitChange(val)}
|
|
433
|
+
controlStyle={{
|
|
434
|
+
minWidth: "70px",
|
|
435
|
+
width: "76px",
|
|
436
|
+
height:
|
|
437
|
+
props.size === "sm"
|
|
438
|
+
? "28px"
|
|
439
|
+
: props.size === "lg"
|
|
440
|
+
? "44px"
|
|
441
|
+
: "36px",
|
|
442
|
+
minHeight:
|
|
443
|
+
props.size === "sm"
|
|
444
|
+
? "28px"
|
|
445
|
+
: props.size === "lg"
|
|
446
|
+
? "44px"
|
|
447
|
+
: "36px",
|
|
448
|
+
padding: "0 8px",
|
|
449
|
+
fontSize: "12px",
|
|
450
|
+
...buildUiVars(props.limitSelectStyle),
|
|
451
|
+
}}
|
|
452
|
+
/>
|
|
453
|
+
) : null}
|
|
454
|
+
</div>
|
|
455
|
+
) : null}
|
|
456
|
+
<ul
|
|
457
|
+
className={`ttdk-pagination-content ${
|
|
458
|
+
props.contentClass || ""
|
|
459
|
+
}`.trim()}
|
|
460
|
+
style={{
|
|
461
|
+
...buildUiVars(props.contentStyle),
|
|
462
|
+
}}
|
|
463
|
+
>
|
|
464
|
+
{props.showEdges || Boolean(props.onFirstPage) ? (
|
|
465
|
+
<li className="ttdk-pagination-item">
|
|
466
|
+
<button
|
|
467
|
+
type="button"
|
|
468
|
+
aria-label="Go to first page"
|
|
469
|
+
className={`ttdk-pagination-link ttdk-pagination-first ${
|
|
470
|
+
props.linkClass || ""
|
|
471
|
+
}`.trim()}
|
|
472
|
+
data-size={props.size || "md"}
|
|
473
|
+
data-disabled={!getCanPrev() ? "true" : "false"}
|
|
474
|
+
disabled={!getCanPrev()}
|
|
475
|
+
onClick={(event) => {
|
|
476
|
+
if (props.onFirstPage) {
|
|
477
|
+
props.onFirstPage();
|
|
478
|
+
} else if (props.onPageChange) {
|
|
479
|
+
props.onPageChange(1);
|
|
480
|
+
}
|
|
481
|
+
}}
|
|
482
|
+
style={{
|
|
483
|
+
...buildUiVars(props.linkStyle),
|
|
484
|
+
}}
|
|
485
|
+
>
|
|
486
|
+
{props.firstIcon ? <>{props.firstIcon}</> : null}
|
|
487
|
+
{!props.firstIcon ? (
|
|
488
|
+
<svg
|
|
489
|
+
className="ttdk-pagination-icon"
|
|
490
|
+
viewBox="0 0 24 24"
|
|
491
|
+
fill="none"
|
|
492
|
+
aria-hidden="true"
|
|
493
|
+
>
|
|
494
|
+
<polyline points="11 17 6 12 11 7" />
|
|
495
|
+
<polyline points="18 17 13 12 18 7" />
|
|
496
|
+
</svg>
|
|
497
|
+
) : null}
|
|
498
|
+
</button>
|
|
499
|
+
</li>
|
|
500
|
+
) : null}
|
|
501
|
+
<li className="ttdk-pagination-item">
|
|
502
|
+
<button
|
|
503
|
+
type="button"
|
|
504
|
+
aria-label="Go to previous page"
|
|
505
|
+
className={`ttdk-pagination-link ttdk-pagination-prev ${
|
|
506
|
+
props.linkClass || ""
|
|
507
|
+
}`.trim()}
|
|
508
|
+
data-size={props.size || "md"}
|
|
509
|
+
data-disabled={!getCanPrev() ? "true" : "false"}
|
|
510
|
+
disabled={!getCanPrev()}
|
|
511
|
+
onClick={(event) => {
|
|
512
|
+
if (props.onPrevPage) {
|
|
513
|
+
props.onPrevPage();
|
|
514
|
+
} else if (props.onPageChange) {
|
|
515
|
+
props.onPageChange(Math.max(1, getCurrentPage() - 1));
|
|
516
|
+
}
|
|
517
|
+
}}
|
|
518
|
+
style={{
|
|
519
|
+
...buildUiVars(props.linkStyle),
|
|
520
|
+
}}
|
|
521
|
+
>
|
|
522
|
+
{props.prevIcon ? <>{props.prevIcon}</> : null}
|
|
523
|
+
{!props.prevIcon ? (
|
|
524
|
+
<svg
|
|
525
|
+
className="ttdk-pagination-icon"
|
|
526
|
+
viewBox="0 0 24 24"
|
|
527
|
+
fill="none"
|
|
528
|
+
aria-hidden="true"
|
|
529
|
+
>
|
|
530
|
+
<polyline points="15 18 9 12 15 6" />
|
|
531
|
+
</svg>
|
|
532
|
+
) : null}
|
|
533
|
+
{!props.iconOnly ? (
|
|
534
|
+
<span className="ttdk-pagination-prev-text">
|
|
535
|
+
{props.prevText || "Previous"}
|
|
536
|
+
</span>
|
|
537
|
+
) : null}
|
|
538
|
+
</button>
|
|
539
|
+
</li>
|
|
540
|
+
{props.showPageNumbers !== false ? (
|
|
541
|
+
<>
|
|
542
|
+
{getPageRange()?.map((item) => (
|
|
543
|
+
<li className="ttdk-pagination-item" key={item.key}>
|
|
544
|
+
{item.type === "ellipsis" ? (
|
|
545
|
+
<span
|
|
546
|
+
aria-hidden="true"
|
|
547
|
+
className="ttdk-pagination-ellipsis"
|
|
548
|
+
>
|
|
549
|
+
{props.ellipsisIcon ? <>{props.ellipsisIcon}</> : null}
|
|
550
|
+
{!props.ellipsisIcon ? (
|
|
551
|
+
<svg
|
|
552
|
+
className="ttdk-pagination-icon"
|
|
553
|
+
viewBox="0 0 24 24"
|
|
554
|
+
fill="none"
|
|
555
|
+
>
|
|
556
|
+
<circle cx="12" cy="12" r="1" />
|
|
557
|
+
<circle cx="19" cy="12" r="1" />
|
|
558
|
+
<circle cx="5" cy="12" r="1" />
|
|
559
|
+
</svg>
|
|
560
|
+
) : null}
|
|
561
|
+
<span className="ttdk-sr-only">More pages</span>
|
|
562
|
+
</span>
|
|
563
|
+
) : null}
|
|
564
|
+
{item.type === "page" ? (
|
|
565
|
+
<button
|
|
566
|
+
type="button"
|
|
567
|
+
className={`ttdk-pagination-link ${
|
|
568
|
+
props.linkClass || ""
|
|
569
|
+
} ${
|
|
570
|
+
item.value === getCurrentPage()
|
|
571
|
+
? props.activeLinkClass || ""
|
|
572
|
+
: ""
|
|
573
|
+
}`.trim()}
|
|
574
|
+
aria-current={
|
|
575
|
+
item.value === getCurrentPage() ? "page" : undefined
|
|
576
|
+
}
|
|
577
|
+
data-active={
|
|
578
|
+
item.value === getCurrentPage() ? "true" : "false"
|
|
579
|
+
}
|
|
580
|
+
data-size={props.size || "md"}
|
|
581
|
+
onClick={(event) => {
|
|
582
|
+
if (props.onPageChange) {
|
|
583
|
+
props.onPageChange(Number(item.value));
|
|
584
|
+
}
|
|
585
|
+
}}
|
|
586
|
+
style={{
|
|
587
|
+
...buildUiVars(props.linkStyle),
|
|
588
|
+
...(item.value === getCurrentPage()
|
|
589
|
+
? buildUiVars(props.activeLinkStyle)
|
|
590
|
+
: {}),
|
|
591
|
+
}}
|
|
592
|
+
>
|
|
593
|
+
{item.value}
|
|
594
|
+
</button>
|
|
595
|
+
) : null}
|
|
596
|
+
</li>
|
|
597
|
+
))}
|
|
598
|
+
</>
|
|
599
|
+
) : null}
|
|
600
|
+
<li className="ttdk-pagination-item">
|
|
601
|
+
<button
|
|
602
|
+
type="button"
|
|
603
|
+
aria-label="Go to next page"
|
|
604
|
+
className={`ttdk-pagination-link ttdk-pagination-next ${
|
|
605
|
+
props.linkClass || ""
|
|
606
|
+
}`.trim()}
|
|
607
|
+
data-size={props.size || "md"}
|
|
608
|
+
data-disabled={!getCanNext() ? "true" : "false"}
|
|
609
|
+
disabled={!getCanNext()}
|
|
610
|
+
onClick={(event) => {
|
|
611
|
+
if (props.onNextPage) {
|
|
612
|
+
props.onNextPage();
|
|
613
|
+
} else if (props.onPageChange) {
|
|
614
|
+
props.onPageChange(
|
|
615
|
+
Math.min(getTotalPages(), getCurrentPage() + 1)
|
|
616
|
+
);
|
|
617
|
+
}
|
|
618
|
+
}}
|
|
619
|
+
style={{
|
|
620
|
+
...buildUiVars(props.linkStyle),
|
|
621
|
+
}}
|
|
622
|
+
>
|
|
623
|
+
{!props.iconOnly ? (
|
|
624
|
+
<span className="ttdk-pagination-next-text">
|
|
625
|
+
{props.nextText || "Next"}
|
|
626
|
+
</span>
|
|
627
|
+
) : null}
|
|
628
|
+
{props.nextIcon ? <>{props.nextIcon}</> : null}
|
|
629
|
+
{!props.nextIcon ? (
|
|
630
|
+
<svg
|
|
631
|
+
className="ttdk-pagination-icon"
|
|
632
|
+
viewBox="0 0 24 24"
|
|
633
|
+
fill="none"
|
|
634
|
+
aria-hidden="true"
|
|
635
|
+
>
|
|
636
|
+
<polyline points="9 18 15 12 9 6" />
|
|
637
|
+
</svg>
|
|
638
|
+
) : null}
|
|
639
|
+
</button>
|
|
640
|
+
</li>
|
|
641
|
+
{props.showEdges || Boolean(props.onLastPage) ? (
|
|
642
|
+
<li className="ttdk-pagination-item">
|
|
643
|
+
<button
|
|
644
|
+
type="button"
|
|
645
|
+
aria-label="Go to last page"
|
|
646
|
+
className={`ttdk-pagination-link ttdk-pagination-last ${
|
|
647
|
+
props.linkClass || ""
|
|
648
|
+
}`.trim()}
|
|
649
|
+
data-size={props.size || "md"}
|
|
650
|
+
data-disabled={!getCanNext() ? "true" : "false"}
|
|
651
|
+
disabled={!getCanNext()}
|
|
652
|
+
onClick={(event) => {
|
|
653
|
+
if (props.onLastPage) {
|
|
654
|
+
props.onLastPage();
|
|
655
|
+
} else if (props.onPageChange) {
|
|
656
|
+
props.onPageChange(getTotalPages());
|
|
657
|
+
}
|
|
658
|
+
}}
|
|
659
|
+
style={{
|
|
660
|
+
...buildUiVars(props.linkStyle),
|
|
661
|
+
}}
|
|
662
|
+
>
|
|
663
|
+
{props.lastIcon ? <>{props.lastIcon}</> : null}
|
|
664
|
+
{!props.lastIcon ? (
|
|
665
|
+
<svg
|
|
666
|
+
className="ttdk-pagination-icon"
|
|
667
|
+
viewBox="0 0 24 24"
|
|
668
|
+
fill="none"
|
|
669
|
+
aria-hidden="true"
|
|
670
|
+
>
|
|
671
|
+
<polyline points="13 17 18 12 13 7" />
|
|
672
|
+
<polyline points="6 17 11 12 6 7" />
|
|
673
|
+
</svg>
|
|
674
|
+
) : null}
|
|
675
|
+
</button>
|
|
676
|
+
</li>
|
|
677
|
+
) : null}
|
|
678
|
+
</ul>
|
|
679
|
+
</div>
|
|
680
|
+
) : null}
|
|
681
|
+
</nav>
|
|
682
|
+
);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
export default Pagination;
|
|
686
|
+
|
|
687
|
+
export { Pagination };
|