@makolabs/ripple 0.0.1-dev.3 → 0.0.1-dev.5

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.
Files changed (102) hide show
  1. package/README.md +229 -96
  2. package/dist/button/Button.svelte +46 -0
  3. package/dist/button/Button.svelte.d.ts +4 -0
  4. package/dist/button/button.d.ts +136 -0
  5. package/dist/button/button.js +167 -0
  6. package/dist/button/index.d.ts +1 -0
  7. package/dist/button/index.js +1 -0
  8. package/dist/drawer/Drawer.svelte +213 -0
  9. package/dist/drawer/Drawer.svelte.d.ts +4 -0
  10. package/dist/drawer/drawer.d.ts +177 -0
  11. package/dist/drawer/drawer.js +80 -0
  12. package/dist/drawer/index.d.ts +2 -0
  13. package/dist/drawer/index.js +1 -0
  14. package/dist/elements/badge/Badge.svelte +35 -0
  15. package/dist/elements/badge/Badge.svelte.d.ts +4 -0
  16. package/dist/elements/badge/badge.d.ts +193 -0
  17. package/dist/elements/badge/badge.js +65 -0
  18. package/dist/elements/badge/index.d.ts +2 -0
  19. package/dist/elements/badge/index.js +2 -0
  20. package/dist/elements/dropdown/Dropdown.svelte +272 -0
  21. package/dist/elements/dropdown/Dropdown.svelte.d.ts +4 -0
  22. package/dist/elements/dropdown/Select.svelte +230 -0
  23. package/dist/elements/dropdown/Select.svelte.d.ts +4 -0
  24. package/dist/elements/dropdown/dropdown.d.ts +274 -0
  25. package/dist/elements/dropdown/dropdown.js +89 -0
  26. package/dist/elements/dropdown/index.d.ts +3 -0
  27. package/dist/elements/dropdown/index.js +2 -0
  28. package/dist/elements/dropdown/select.d.ts +220 -0
  29. package/dist/elements/dropdown/select.js +74 -0
  30. package/dist/header/Breadcrumbs.svelte +72 -0
  31. package/dist/header/Breadcrumbs.svelte.d.ts +4 -0
  32. package/dist/header/PageHeader.svelte +30 -0
  33. package/dist/header/PageHeader.svelte.d.ts +4 -0
  34. package/dist/header/breadcrumbs.d.ts +220 -0
  35. package/dist/header/breadcrumbs.js +81 -0
  36. package/dist/header/index.d.ts +4 -0
  37. package/dist/header/index.js +2 -0
  38. package/dist/header/pageheaders.d.ts +10 -0
  39. package/dist/header/pageheaders.js +1 -0
  40. package/dist/helper/cls.d.ts +1 -0
  41. package/dist/helper/cls.js +4 -0
  42. package/dist/helper/nav.svelte.d.ts +6 -0
  43. package/dist/helper/nav.svelte.js +23 -0
  44. package/dist/index.d.ts +10 -1
  45. package/dist/index.js +18 -1
  46. package/dist/layout/card/Card.svelte +44 -0
  47. package/dist/layout/card/Card.svelte.d.ts +4 -0
  48. package/dist/layout/card/StatsCard.svelte +236 -0
  49. package/dist/layout/card/StatsCard.svelte.d.ts +4 -0
  50. package/dist/layout/card/card.d.ts +139 -0
  51. package/dist/layout/card/card.js +50 -0
  52. package/dist/layout/card/index.d.ts +4 -0
  53. package/dist/layout/card/index.js +2 -0
  54. package/dist/layout/card/stats-card.d.ts +208 -0
  55. package/dist/layout/card/stats-card.js +73 -0
  56. package/dist/layout/index.d.ts +5 -1
  57. package/dist/layout/index.js +5 -1
  58. package/dist/layout/navbar/Navbar.svelte +206 -0
  59. package/dist/layout/navbar/Navbar.svelte.d.ts +4 -0
  60. package/dist/layout/navbar/index.d.ts +2 -0
  61. package/dist/layout/navbar/index.js +2 -0
  62. package/dist/layout/navbar/navbar.d.ts +228 -0
  63. package/dist/layout/navbar/navbar.js +98 -0
  64. package/dist/layout/sidebar/NavGroup.svelte +101 -0
  65. package/dist/layout/sidebar/NavGroup.svelte.d.ts +4 -0
  66. package/dist/layout/sidebar/NavItem.svelte +29 -0
  67. package/dist/layout/sidebar/NavItem.svelte.d.ts +4 -0
  68. package/dist/layout/sidebar/Sidebar.svelte +145 -0
  69. package/dist/layout/sidebar/Sidebar.svelte.d.ts +4 -0
  70. package/dist/layout/sidebar/index.d.ts +2 -0
  71. package/dist/layout/sidebar/index.js +1 -0
  72. package/dist/layout/sidebar/sidebar.d.ts +46 -0
  73. package/dist/layout/sidebar/sidebar.js +1 -0
  74. package/dist/layout/table/Cells.svelte +111 -0
  75. package/dist/layout/table/Cells.svelte.d.ts +27 -0
  76. package/dist/layout/table/Table.svelte +413 -0
  77. package/dist/layout/table/Table.svelte.d.ts +4 -0
  78. package/dist/layout/table/index.d.ts +3 -0
  79. package/dist/layout/table/index.js +2 -0
  80. package/dist/layout/table/table.d.ts +303 -0
  81. package/dist/layout/table/table.js +149 -0
  82. package/dist/layout/tabs/Tab.svelte +57 -0
  83. package/dist/layout/tabs/Tab.svelte.d.ts +4 -0
  84. package/dist/layout/tabs/TabContent.svelte +31 -0
  85. package/dist/layout/tabs/TabContent.svelte.d.ts +4 -0
  86. package/dist/layout/tabs/TabGroup.svelte +57 -0
  87. package/dist/layout/tabs/TabGroup.svelte.d.ts +4 -0
  88. package/dist/layout/tabs/index.d.ts +3 -0
  89. package/dist/layout/tabs/index.js +3 -0
  90. package/dist/layout/tabs/tabs.d.ts +155 -0
  91. package/dist/layout/tabs/tabs.js +156 -0
  92. package/dist/modal/Modal.svelte +206 -0
  93. package/dist/modal/Modal.svelte.d.ts +4 -0
  94. package/dist/modal/index.d.ts +1 -0
  95. package/dist/modal/index.js +1 -0
  96. package/dist/modal/modal.d.ts +234 -0
  97. package/dist/modal/modal.js +81 -0
  98. package/dist/types/variants.d.ts +21 -0
  99. package/dist/types/variants.js +19 -0
  100. package/package.json +100 -102
  101. package/dist/layout/Card.svelte +0 -179
  102. package/dist/layout/Card.svelte.d.ts +0 -208
@@ -0,0 +1,111 @@
1
+ <script module lang="ts">
2
+ import type { StatusType, KeyType, DataRow } from './table.js';
3
+
4
+ export { DateCell, Currency, Percentage, PhoneNumber, Email, Status, Time };
5
+
6
+ function getStatusClass(status: string): KeyType {
7
+ const base = 'inline-flex px-2 py-1 text-xs font-medium rounded-full';
8
+ const classes: Record<StatusType, string> = {
9
+ active: `${base} bg-success-100 text-success-700`,
10
+ inactive: `${base} bg-default-100 text-default-700`,
11
+ pending: `${base} bg-warning-100 text-warning-700`,
12
+ error: `${base} bg-danger-100 text-danger-700`,
13
+ default: `${base} bg-default-100 text-default-700`
14
+ };
15
+ return classes[status as StatusType] || classes.default;
16
+ }
17
+
18
+ function formatPhoneNumber(phoneNumber: string | number | null | undefined): KeyType | null {
19
+ if (phoneNumber === undefined || phoneNumber === null) {
20
+ return null;
21
+ }
22
+ const clean = String(phoneNumber).replace(/\D/g, '');
23
+ const match = clean.match(/^(\d{3})(\d{3})(\d{4})$/);
24
+ return match ? `(${match[1]}) ${match[2]}-${match[3]}` : String(phoneNumber);
25
+ }
26
+
27
+ function formatTime(time: string | number | Date): KeyType {
28
+ return new Date(time).toLocaleTimeString('en-US', {
29
+ hour: '2-digit',
30
+ minute: '2-digit'
31
+ });
32
+ }
33
+
34
+ function formatCurrency(value: number): KeyType {
35
+ return new Intl.NumberFormat('en-US', {
36
+ style: 'currency',
37
+ currency: 'USD',
38
+ minimumFractionDigits: 2,
39
+ maximumFractionDigits: 2
40
+ }).format(value);
41
+ }
42
+
43
+ function formatPercentage(value: number): KeyType {
44
+ return new Intl.NumberFormat('en-US', {
45
+ style: 'percent',
46
+ minimumFractionDigits: 2,
47
+ maximumFractionDigits: 2
48
+ }).format(value / 100);
49
+ }
50
+ </script>
51
+
52
+ {#snippet DateCell(row: DataRow, key: KeyType)}
53
+ {#if row[key] !== undefined && row[key] !== null}
54
+ {new Date(row[key]).toLocaleDateString('en-US')}
55
+ {:else}
56
+ <span class="text-default-300">—</span>
57
+ {/if}
58
+ {/snippet}
59
+
60
+ {#snippet Currency(row: DataRow, key: KeyType)}
61
+ {#if row[key] !== undefined && row[key] !== null}
62
+ {formatCurrency(row[key])}
63
+ {:else}
64
+ <span class="text-default-300">—</span>
65
+ {/if}
66
+ {/snippet}
67
+
68
+ {#snippet Percentage(row: DataRow, key: KeyType)}
69
+ {#if row[key] !== undefined && row[key] !== null}
70
+ {formatPercentage(row[key])}
71
+ {:else}
72
+ <span class="text-default-300">—</span>
73
+ {/if}
74
+ {/snippet}
75
+
76
+ {#snippet PhoneNumber(row: DataRow, key: KeyType)}
77
+ {#if row[key] !== undefined && row[key] !== null}
78
+ {formatPhoneNumber(row[key])}
79
+ {:else}
80
+ <span class="text-default-300">—</span>
81
+ {/if}
82
+ {/snippet}
83
+
84
+ {#snippet Email(row: DataRow, key: KeyType)}
85
+ {#if row[key] !== undefined && row[key] !== null}
86
+ <a href="mailto:{row[key]}" class="text-primary-600 hover:underline">
87
+ {row[key]}
88
+ </a>
89
+ {:else}
90
+ <span class="text-default-300">—</span>
91
+ {/if}
92
+ {/snippet}
93
+
94
+ {#snippet Status(row: DataRow, key: KeyType)}
95
+ {#if row[key] !== undefined && row[key] !== null}
96
+ {@const status = String(row[key]).toLowerCase()}
97
+ <span class={getStatusClass(status)}>
98
+ {row[key]}
99
+ </span>
100
+ {:else}
101
+ <span class="text-default-300">—</span>
102
+ {/if}
103
+ {/snippet}
104
+
105
+ {#snippet Time(row: DataRow, key: KeyType)}
106
+ {#if row[key] !== undefined && row[key] !== null}
107
+ {formatTime(row[key])}
108
+ {:else}
109
+ <span class="text-default-300">—</span>
110
+ {/if}
111
+ {/snippet}
@@ -0,0 +1,27 @@
1
+ import type { KeyType, DataRow } from './table.js';
2
+ export { DateCell, Currency, Percentage, PhoneNumber, Email, Status, Time };
3
+ declare const DateCell: (row: DataRow, key: KeyType) => ReturnType<import("svelte").Snippet>;
4
+ declare const Currency: (row: DataRow, key: KeyType) => ReturnType<import("svelte").Snippet>;
5
+ declare const Percentage: (row: DataRow, key: KeyType) => ReturnType<import("svelte").Snippet>;
6
+ declare const PhoneNumber: (row: DataRow, key: KeyType) => ReturnType<import("svelte").Snippet>;
7
+ declare const Email: (row: DataRow, key: KeyType) => ReturnType<import("svelte").Snippet>;
8
+ declare const Status: (row: DataRow, key: KeyType) => ReturnType<import("svelte").Snippet>;
9
+ declare const Time: (row: DataRow, key: KeyType) => ReturnType<import("svelte").Snippet>;
10
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
11
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
12
+ $$bindings?: Bindings;
13
+ } & Exports;
14
+ (internal: unknown, props: {
15
+ $$events?: Events;
16
+ $$slots?: Slots;
17
+ }): Exports & {
18
+ $set?: any;
19
+ $on?: any;
20
+ };
21
+ z_$$bindings?: Bindings;
22
+ }
23
+ declare const Cells: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
24
+ [evt: string]: CustomEvent<any>;
25
+ }, {}, {}, string>;
26
+ type Cells = InstanceType<typeof Cells>;
27
+ export default Cells;
@@ -0,0 +1,413 @@
1
+ <script lang="ts">
2
+ import { cn } from '../../helper/cls.js';
3
+ import { table, type TableProps, type SortDirection, type SortState } from './table.js';
4
+
5
+ let {
6
+ data = [],
7
+ columns = [],
8
+ color = 'default',
9
+ size = 'base',
10
+ bordered = true,
11
+ striped = false,
12
+ pageSize = 10,
13
+ selectable = false,
14
+ selected = $bindable([]),
15
+ onrowclick = () => {},
16
+ onsort = () => {},
17
+ onselect = () => {},
18
+ class: classname = '',
19
+ wrapperclass: wrapperClass = '',
20
+ tableclass: tableClass = '',
21
+ theadclass: theadClass = '',
22
+ tbodyclass: tbodyClass = '',
23
+ trclass: trClass = '',
24
+ thclass: thClass = '',
25
+ tdclass: tdClass = '',
26
+ footerclass: footerClass = '',
27
+ rowclass = () => '',
28
+ loading = false
29
+ }: TableProps<any> = $props();
30
+
31
+ let sortColumn = $state('');
32
+ let sortDirection = $state<SortDirection>(null);
33
+ let currentPage = $state(1);
34
+
35
+ // Pagination is automatically determined by pageSize
36
+ const pagination = $derived(pageSize > 0 && data.length > pageSize);
37
+
38
+ const {
39
+ base,
40
+ wrapper,
41
+ table: tableBaseClass,
42
+ thead,
43
+ tbody,
44
+ tr,
45
+ th,
46
+ td,
47
+ footer,
48
+ pagination: paginationClass,
49
+ emptyState,
50
+ sortButton,
51
+ sortIcon
52
+ } = $derived(
53
+ table({
54
+ size,
55
+ color,
56
+ bordered,
57
+ striped
58
+ })
59
+ );
60
+
61
+ const baseClasses = $derived(cn(base(), classname));
62
+ const wrapperClasses = $derived(cn(wrapper(), wrapperClass));
63
+ const tableClasses = $derived(cn(tableBaseClass(), tableClass));
64
+ const theadClasses = $derived(cn(thead(), theadClass));
65
+ const tbodyClasses = $derived(cn(tbody(), tbodyClass));
66
+ const trClasses = $derived(cn(tr(), trClass));
67
+ const thClasses = $derived(cn(th(), thClass));
68
+ const tdClasses = $derived(cn(td(), tdClass));
69
+ const footerClasses = $derived(cn(footer(), footerClass));
70
+ const emptyStateClasses = $derived(emptyState());
71
+
72
+ // Handle pagination
73
+ const totalPages = $derived(Math.ceil(data.length / pageSize));
74
+ const paginatedData = $derived(
75
+ pagination ? data.slice((currentPage - 1) * pageSize, currentPage * pageSize) : data
76
+ );
77
+
78
+ // Handle sorting
79
+ function toggleSort(column: string) {
80
+ const columnDef = columns.find((col) => (col.sortKey || col.key) === column);
81
+ if (!columnDef?.sortable) return;
82
+
83
+ if (sortColumn === column) {
84
+ // Cycle through: asc -> desc -> null
85
+ if (sortDirection === 'asc') {
86
+ sortDirection = 'desc';
87
+ } else if (sortDirection === 'desc') {
88
+ sortDirection = null;
89
+ sortColumn = '';
90
+ } else {
91
+ sortDirection = 'asc';
92
+ }
93
+ } else {
94
+ sortColumn = column;
95
+ sortDirection = 'asc';
96
+ }
97
+
98
+ const newSortState: SortState = { column: sortColumn, direction: sortDirection };
99
+ onsort(newSortState);
100
+ }
101
+
102
+ function toggleRowSelection(row: any) {
103
+ if (!selectable) return;
104
+
105
+ const index = selected.findIndex((r) => r === row);
106
+ if (index === -1) {
107
+ selected = [...selected, row];
108
+ } else {
109
+ selected = selected.filter((r) => r !== row);
110
+ }
111
+
112
+ onselect(selected);
113
+ }
114
+
115
+ function isRowSelected(row: any) {
116
+ return selected.includes(row);
117
+ }
118
+
119
+ function handleRowClick(row: any, index: number) {
120
+ onrowclick(row, index);
121
+ }
122
+
123
+ function nextPage() {
124
+ if (currentPage < totalPages) {
125
+ currentPage++;
126
+ }
127
+ }
128
+
129
+ function prevPage() {
130
+ if (currentPage > 1) {
131
+ currentPage--;
132
+ }
133
+ }
134
+
135
+ function goToPage(page: number) {
136
+ if (page >= 1 && page <= totalPages) {
137
+ currentPage = page;
138
+ }
139
+ }
140
+ </script>
141
+
142
+ <div class={baseClasses}>
143
+ <div class={wrapperClasses}>
144
+ <table class={tableClasses}>
145
+ <thead class={theadClasses}>
146
+ <tr>
147
+ {#if selectable}
148
+ <th class={thClasses}>
149
+ <input
150
+ type="checkbox"
151
+ onchange={() => {
152
+ if (selected.length === data.length) {
153
+ selected = [];
154
+ } else {
155
+ selected = [...data];
156
+ }
157
+ onselect(selected);
158
+ }}
159
+ checked={selected.length === data.length && data.length > 0}
160
+ aria-label="Select all rows"
161
+ />
162
+ </th>
163
+ {/if}
164
+
165
+ {#each columns as column (column.key)}
166
+ <th
167
+ class={cn(
168
+ thClasses,
169
+ column.align === 'center' && 'text-center',
170
+ column.align === 'right' && 'text-right',
171
+ column.class
172
+ )}
173
+ style={column.width ? `width: ${column.width}` : undefined}
174
+ >
175
+ {#if column.sortable}
176
+ <button
177
+ type="button"
178
+ class={sortButton()}
179
+ onclick={() => toggleSort(column.sortKey || column.key)}
180
+ aria-label={`Sort by ${column.header}`}
181
+ >
182
+ {column.header}
183
+ <span class={sortIcon()}>
184
+ {#if sortColumn === (column.sortKey || column.key)}
185
+ {#if sortDirection === 'asc'}
186
+ <svg
187
+ xmlns="http://www.w3.org/2000/svg"
188
+ viewBox="0 0 20 20"
189
+ fill="currentColor"
190
+ class="h-4 w-4"
191
+ >
192
+ <path
193
+ d="M10 15a.75.75 0 01-.75-.75V7.612L6.058 10.8a.75.75 0 01-1.061-1.061l3.75-3.75a.75.75 0 011.06 0l3.75 3.75a.75.75 0 11-1.06 1.061L10.75 7.612v6.638A.75.75 0 0110 15z"
194
+ />
195
+ </svg>
196
+ {:else if sortDirection === 'desc'}
197
+ <svg
198
+ xmlns="http://www.w3.org/2000/svg"
199
+ viewBox="0 0 20 20"
200
+ fill="currentColor"
201
+ class="h-4 w-4"
202
+ >
203
+ <path
204
+ d="M10 5a.75.75 0 01.75.75v6.638l3.192-3.187a.75.75 0 111.06 1.061l-3.75 3.75a.75.75 0 01-1.06 0l-3.75-3.75a.75.75 0 111.06-1.061L9.25 12.389V5.75A.75.75 0 0110 5z"
205
+ />
206
+ </svg>
207
+ {/if}
208
+ {:else}
209
+ <svg
210
+ xmlns="http://www.w3.org/2000/svg"
211
+ fill="none"
212
+ viewBox="0 0 24 24"
213
+ stroke-width="1.5"
214
+ stroke="currentColor"
215
+ class="h-4 w-4 opacity-40"
216
+ >
217
+ <path
218
+ stroke-linecap="round"
219
+ stroke-linejoin="round"
220
+ d="M8.25 15L12 18.75 15.75 15m-7.5-6L12 5.25 15.75 9"
221
+ />
222
+ </svg>
223
+ {/if}
224
+ </span>
225
+ </button>
226
+ {:else}
227
+ {column.header}
228
+ {/if}
229
+ </th>
230
+ {/each}
231
+ </tr>
232
+ </thead>
233
+
234
+ <tbody class={tbodyClasses}>
235
+ {#if loading}
236
+ <tr>
237
+ <td
238
+ colspan={selectable ? columns.length + 1 : columns.length}
239
+ class={cn(tdClasses, 'py-8 text-center')}
240
+ >
241
+ <div class="flex justify-center">
242
+ <svg
243
+ class="text-default-500 h-6 w-6 animate-spin"
244
+ xmlns="http://www.w3.org/2000/svg"
245
+ fill="none"
246
+ viewBox="0 0 24 24"
247
+ >
248
+ <circle
249
+ class="opacity-25"
250
+ cx="12"
251
+ cy="12"
252
+ r="10"
253
+ stroke="currentColor"
254
+ stroke-width="4"
255
+ ></circle>
256
+ <path
257
+ class="opacity-75"
258
+ fill="currentColor"
259
+ d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
260
+ ></path>
261
+ </svg>
262
+ </div>
263
+ </td>
264
+ </tr>
265
+ {:else if paginatedData.length === 0}
266
+ <tr>
267
+ <td
268
+ colspan={selectable ? columns.length + 1 : columns.length}
269
+ class={emptyStateClasses}
270
+ >
271
+ No data available
272
+ </td>
273
+ </tr>
274
+ {:else}
275
+ {#each paginatedData as row, rowIndex (rowIndex)}
276
+ <tr
277
+ class={cn(
278
+ trClasses,
279
+ rowclass(row, rowIndex),
280
+ selectable && isRowSelected(row) && 'bg-primary-100'
281
+ )}
282
+ onclick={() => handleRowClick(row, rowIndex)}
283
+ aria-selected={selectable && isRowSelected(row)}
284
+ >
285
+ {#if selectable}
286
+ <td class={tdClasses}>
287
+ <input
288
+ type="checkbox"
289
+ checked={isRowSelected(row)}
290
+ onclick={(e) => {
291
+ e.stopPropagation(); // Prevent row click
292
+ toggleRowSelection(row);
293
+ }}
294
+ aria-label={`Select row ${rowIndex + 1}`}
295
+ />
296
+ </td>
297
+ {/if}
298
+
299
+ {#each columns as column (column.key)}
300
+ <td
301
+ class={cn(
302
+ tdClasses,
303
+ column.align === 'center' && 'text-center',
304
+ column.align === 'right' && 'text-right',
305
+ column.class
306
+ )}
307
+ >
308
+ {#if column.cell}
309
+ {@render column.cell(row, column.key, rowIndex)}
310
+ {:else if row[column.key] === undefined || row[column.key] === null}
311
+ <span class="text-default-300">—</span>
312
+ {:else}
313
+ {row[column.key]}
314
+ {/if}
315
+ </td>
316
+ {/each}
317
+ </tr>
318
+ {/each}
319
+ {/if}
320
+ </tbody>
321
+ </table>
322
+ </div>
323
+
324
+ {#if pagination && totalPages > 1}
325
+ <div class={footerClasses}>
326
+ <div class={paginationClass}>
327
+ <div class="flex items-center gap-2">
328
+ <span class="text-default-500 text-sm">
329
+ Showing {Math.min((currentPage - 1) * pageSize + 1, data.length)}
330
+ to {Math.min(currentPage * pageSize, data.length)} of {data.length} entries
331
+ </span>
332
+ </div>
333
+
334
+ <div class="flex items-center gap-1">
335
+ <button
336
+ type="button"
337
+ class={cn(
338
+ 'relative inline-flex items-center rounded-md px-2 py-1 text-sm font-medium',
339
+ currentPage === 1
340
+ ? 'text-default-300 cursor-not-allowed'
341
+ : 'text-default-700 hover:bg-default-100'
342
+ )}
343
+ onclick={prevPage}
344
+ disabled={currentPage === 1}
345
+ aria-label="Previous page"
346
+ >
347
+ <svg
348
+ xmlns="http://www.w3.org/2000/svg"
349
+ viewBox="0 0 20 20"
350
+ fill="currentColor"
351
+ class="h-5 w-5"
352
+ >
353
+ <path
354
+ 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"
355
+ />
356
+ </svg>
357
+ </button>
358
+
359
+ <!--eslint-disable-next-line @typescript-eslint/no-unused-vars-->
360
+ {#each Array(Math.min(5, totalPages)) as _, i (i)}
361
+ {@const pageNum =
362
+ currentPage <= 3
363
+ ? i + 1
364
+ : currentPage >= totalPages - 2
365
+ ? totalPages - 4 + i
366
+ : currentPage - 2 + i}
367
+
368
+ {#if pageNum > 0 && pageNum <= totalPages}
369
+ <button
370
+ type="button"
371
+ class={cn(
372
+ 'relative inline-flex items-center rounded-md px-3 py-1 text-sm font-medium',
373
+ currentPage === pageNum
374
+ ? 'bg-primary-100 text-primary-700'
375
+ : 'text-default-700 hover:bg-default-100'
376
+ )}
377
+ onclick={() => goToPage(pageNum)}
378
+ aria-label={`Page ${pageNum}`}
379
+ aria-current={currentPage === pageNum ? 'page' : undefined}
380
+ >
381
+ {pageNum}
382
+ </button>
383
+ {/if}
384
+ {/each}
385
+
386
+ <button
387
+ type="button"
388
+ class={cn(
389
+ 'relative inline-flex items-center rounded-md px-2 py-1 text-sm font-medium',
390
+ currentPage === totalPages
391
+ ? 'text-default-300 cursor-not-allowed'
392
+ : 'text-default-700 hover:bg-default-100'
393
+ )}
394
+ onclick={nextPage}
395
+ disabled={currentPage === totalPages}
396
+ aria-label="Next page"
397
+ >
398
+ <svg
399
+ xmlns="http://www.w3.org/2000/svg"
400
+ viewBox="0 0 20 20"
401
+ fill="currentColor"
402
+ class="h-5 w-5"
403
+ >
404
+ <path
405
+ 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"
406
+ />
407
+ </svg>
408
+ </button>
409
+ </div>
410
+ </div>
411
+ </div>
412
+ {/if}
413
+ </div>
@@ -0,0 +1,4 @@
1
+ import { type TableProps } from './table.js';
2
+ declare const Table: import("svelte").Component<TableProps<any>, {}, "selected">;
3
+ type Table = ReturnType<typeof Table>;
4
+ export default Table;
@@ -0,0 +1,3 @@
1
+ export { default as Table } from './Table.svelte';
2
+ export type { TableProps, KeyType, DataRow, StatusType, TableColumn, SortState, SortDirection } from './table.js';
3
+ export { default as Cells } from './Cells.svelte';
@@ -0,0 +1,2 @@
1
+ export { default as Table } from './Table.svelte';
2
+ export { default as Cells } from './Cells.svelte';