@kikiloaw/simple-table 1.1.4 → 1.1.10
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 +8 -13
- package/package.json +1 -1
- package/src/SimpleTable.vue +47 -22
package/README.md
CHANGED
|
@@ -30,14 +30,8 @@
|
|
|
30
30
|
npm install @kikiloaw/simple-table
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
### Option 2: Local Copy
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
cp -r path/to/SimpleTable /your-project/src/components/
|
|
37
|
-
```
|
|
38
33
|
|
|
39
34
|
---
|
|
40
|
-
|
|
41
35
|
## 🚀 Quick Start
|
|
42
36
|
|
|
43
37
|
### 1. Import the Component
|
|
@@ -422,10 +416,10 @@ SimpleTable supports three data modes:
|
|
|
422
416
|
|
|
423
417
|
### Protocol Formats
|
|
424
418
|
|
|
425
|
-
| Protocol | When to Use | Backend
|
|
426
|
-
|
|
427
|
-
| **`laravel`** (default) |
|
|
428
|
-
| **`datatables`** |
|
|
419
|
+
| Protocol | When to Use | Backend Compatibility |
|
|
420
|
+
|----------|-------------|-----------------------|
|
|
421
|
+
| **`laravel`** (default) | **Recommended for 99% of cases.** | Standard Laravel pagination, Resource Collections, and custom JSON responses (including simple DataTables-like backends). |
|
|
422
|
+
| **`datatables`** | Rare. | Only use if your backend **strictly requires** `draw`, `start`, and `length` request parameters and fails with standard `page`/`per_page` params. |
|
|
429
423
|
|
|
430
424
|
---
|
|
431
425
|
|
|
@@ -464,6 +458,7 @@ SimpleTable supports three data modes:
|
|
|
464
458
|
| `oddRowColor` | String | `'bg-white'` | Tailwind class for odd rows |
|
|
465
459
|
| `evenRowColor` | String | `'bg-stone-100'` | Tailwind class for even rows |
|
|
466
460
|
| `hoverColor` | String | `'hover:bg-stone-200'` | Tailwind class for row hover |
|
|
461
|
+
| `paginationColor` | String | `'#2563eb'` | Hex color for active pagination button |
|
|
467
462
|
|
|
468
463
|
---
|
|
469
464
|
|
|
@@ -1422,9 +1417,9 @@ tableRef.value?.refresh()
|
|
|
1422
1417
|
|
|
1423
1418
|
| Method | Parameters | Description |
|
|
1424
1419
|
|--------|------------|-------------|
|
|
1425
|
-
| `refresh()` | None | Resets
|
|
1426
|
-
| `fetchData(params)` | `params
|
|
1427
|
-
| `clearCache()` |
|
|
1420
|
+
| `refresh()` | None | **Resets to Page 1** and refetches data. Use for "Reset" actions. |
|
|
1421
|
+
| `fetchData(params)` | `params?: Object` | Refetches **current page** (if no params). Pass params to override (e.g. `{ page: 1 }`). |
|
|
1422
|
+
| `clearCache(scope)` | `scope?: 'all' \| 'current'` | Clears cache. Default `'all'` clears everything. Pass `'current'` to clear only active page state. |
|
|
1428
1423
|
|
|
1429
1424
|
---
|
|
1430
1425
|
|
package/package.json
CHANGED
package/src/SimpleTable.vue
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
import { useDebounceFn } from '@vueuse/core'
|
|
15
|
+
import { useDebounceFn, useWindowSize } from '@vueuse/core'
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Props definition
|
|
@@ -49,6 +49,7 @@ interface Props {
|
|
|
49
49
|
oddRowColor?: string // Tailwind color class, e.g. 'bg-white'
|
|
50
50
|
evenRowColor?: string // Tailwind color class, e.g. 'bg-gray-50'
|
|
51
51
|
hoverColor?: string // Tailwind color class for hover, e.g. 'hover:bg-gray-100'. If passed, we'll try to apply group-hover for fixed cols.
|
|
52
|
+
paginationColor?: string // Hex color for active pagination button (default: #2563eb)
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
const props = withDefaults(defineProps<Props>(), {
|
|
@@ -193,8 +194,13 @@ function getCacheKey(): string {
|
|
|
193
194
|
})
|
|
194
195
|
}
|
|
195
196
|
|
|
196
|
-
function clearCache() {
|
|
197
|
-
|
|
197
|
+
function clearCache(scope: 'all' | 'current' = 'all') {
|
|
198
|
+
if (scope === 'current') {
|
|
199
|
+
const key = getCacheKey()
|
|
200
|
+
responseCache.value.delete(key)
|
|
201
|
+
} else {
|
|
202
|
+
responseCache.value.clear()
|
|
203
|
+
}
|
|
198
204
|
}
|
|
199
205
|
|
|
200
206
|
// Internal data state to handle both props updates and ajax updates
|
|
@@ -225,13 +231,24 @@ const serverMeta = computed(() => {
|
|
|
225
231
|
const d = internalData.value as any
|
|
226
232
|
// Handle standard Laravel Paginator or Resource Collection
|
|
227
233
|
const meta = d.meta || d
|
|
234
|
+
|
|
235
|
+
// Polyfill missing 'from' and 'to' if server response (like DataTables custom backend) omits them
|
|
236
|
+
const page = meta.current_page ?? 1
|
|
237
|
+
const pPage = meta.per_page ?? currentPerPage.value
|
|
238
|
+
const total = meta.total ?? 0
|
|
239
|
+
const dataCount = Array.isArray(d.data) ? d.data.length : 0
|
|
240
|
+
|
|
241
|
+
// Calculate fallback values
|
|
242
|
+
const calculatedFrom = total === 0 ? 0 : ((page - 1) * pPage) + 1
|
|
243
|
+
const calculatedTo = total === 0 ? 0 : Math.min(calculatedFrom + dataCount - 1, total)
|
|
244
|
+
|
|
228
245
|
return {
|
|
229
|
-
current_page:
|
|
246
|
+
current_page: page,
|
|
230
247
|
last_page: meta.last_page ?? 1,
|
|
231
|
-
per_page:
|
|
232
|
-
from: meta.from ??
|
|
233
|
-
to: meta.to ??
|
|
234
|
-
total:
|
|
248
|
+
per_page: pPage,
|
|
249
|
+
from: meta.from ?? calculatedFrom,
|
|
250
|
+
to: meta.to ?? calculatedTo,
|
|
251
|
+
total: total,
|
|
235
252
|
links: meta.links ?? []
|
|
236
253
|
}
|
|
237
254
|
})
|
|
@@ -325,9 +342,16 @@ const paginationMeta = computed(() => {
|
|
|
325
342
|
|
|
326
343
|
// -- Computed: Page Numbers for Pagination --
|
|
327
344
|
const pageNumbers = computed(() => {
|
|
328
|
-
const
|
|
329
|
-
const
|
|
330
|
-
const
|
|
345
|
+
const { width } = useWindowSize()
|
|
346
|
+
const isMobile = width.value < 640
|
|
347
|
+
const isExtraSmall = width.value < 550
|
|
348
|
+
|
|
349
|
+
const current = Number(isServerSide.value ? (serverMeta.value?.current_page || 1) : currentPage.value)
|
|
350
|
+
const total = Number(totalPages.value)
|
|
351
|
+
// Show fewer surrounding pages on mobile to prevent overflow
|
|
352
|
+
// delta = 0 means only current page (plus first/last)
|
|
353
|
+
const delta = isExtraSmall ? 0 : (isMobile ? 1 : 2)
|
|
354
|
+
|
|
331
355
|
const pages: (number | string)[] = []
|
|
332
356
|
|
|
333
357
|
// Always show first page
|
|
@@ -948,16 +972,16 @@ function getCellStyle(col: any, index: number, totalCols: number) {
|
|
|
948
972
|
</div>
|
|
949
973
|
|
|
950
974
|
<!-- Pagination -->
|
|
951
|
-
<div class="flex items-center justify-between px-2">
|
|
975
|
+
<div class="flex items-center justify-between flex-wrap gap-4 px-2 py-2">
|
|
952
976
|
<div class="text-sm text-gray-500">
|
|
953
977
|
Showing {{ paginationMeta.from }} to {{ paginationMeta.to }} of {{ paginationMeta.total }} results
|
|
954
978
|
</div>
|
|
955
979
|
<div class="flex items-center space-x-1">
|
|
956
980
|
<!-- Previous Button -->
|
|
957
981
|
<button
|
|
958
|
-
class="inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-gray-300 bg-white hover:bg-gray-100 hover:text-gray-900 h-9 px-3"
|
|
959
|
-
:disabled="(isServerSide ? serverMeta?.current_page === 1 : currentPage === 1)"
|
|
960
|
-
@click="handlePageChange(isServerSide ? (serverMeta?.current_page || 1) - 1 : currentPage - 1)"
|
|
982
|
+
class="inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-gray-300 bg-white hover:bg-gray-100 hover:text-gray-900 h-9 px-2 sm:px-3"
|
|
983
|
+
:disabled="(isServerSide ? Number(serverMeta?.current_page) === 1 : currentPage === 1)"
|
|
984
|
+
@click="handlePageChange(isServerSide ? (Number(serverMeta?.current_page || 1)) - 1 : currentPage - 1)"
|
|
961
985
|
>
|
|
962
986
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4"><path d="m15 18-6-6 6-6"/></svg>
|
|
963
987
|
<span class="ml-1 hidden sm:inline">Previous</span>
|
|
@@ -968,7 +992,7 @@ function getCellStyle(col: any, index: number, totalCols: number) {
|
|
|
968
992
|
<!-- Ellipsis -->
|
|
969
993
|
<span
|
|
970
994
|
v-if="page === '...'"
|
|
971
|
-
class="inline-flex items-center justify-center h-9 px-3 text-sm text-gray-500"
|
|
995
|
+
class="inline-flex items-center justify-center h-9 px-2 sm:px-3 text-sm text-gray-500"
|
|
972
996
|
>
|
|
973
997
|
...
|
|
974
998
|
</span>
|
|
@@ -976,12 +1000,13 @@ function getCellStyle(col: any, index: number, totalCols: number) {
|
|
|
976
1000
|
<!-- Page Number Button -->
|
|
977
1001
|
<button
|
|
978
1002
|
v-else
|
|
979
|
-
class="inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border h-9 min-w-[36px] px-3"
|
|
1003
|
+
class="inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border h-9 min-w-[36px] px-2 sm:px-3"
|
|
980
1004
|
:class="[
|
|
981
|
-
(isServerSide ? serverMeta?.current_page === page : currentPage === page)
|
|
982
|
-
? '
|
|
1005
|
+
(isServerSide ? Number(serverMeta?.current_page) === page : currentPage === page)
|
|
1006
|
+
? 'hover:bg-blue-700'
|
|
983
1007
|
: 'border-gray-300 bg-white hover:bg-gray-100 hover:text-gray-900'
|
|
984
1008
|
]"
|
|
1009
|
+
:style="(isServerSide ? Number(serverMeta?.current_page) === page : currentPage === page) ? `background-color: ${props.paginationColor || '#2563eb'} !important; color: white !important; border-color: ${props.paginationColor || '#2563eb'} !important;` : ''"
|
|
985
1010
|
@click="handlePageChange(page as number)"
|
|
986
1011
|
>
|
|
987
1012
|
{{ page }}
|
|
@@ -990,9 +1015,9 @@ function getCellStyle(col: any, index: number, totalCols: number) {
|
|
|
990
1015
|
|
|
991
1016
|
<!-- Next Button -->
|
|
992
1017
|
<button
|
|
993
|
-
class="inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-gray-300 bg-white hover:bg-gray-100 hover:text-gray-900 h-9 px-3"
|
|
994
|
-
:disabled="(isServerSide ? serverMeta?.current_page === serverMeta?.last_page : currentPage === totalPages)"
|
|
995
|
-
@click="handlePageChange(isServerSide ? (serverMeta?.current_page || 1) + 1 : currentPage + 1)"
|
|
1018
|
+
class="inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-gray-300 bg-white hover:bg-gray-100 hover:text-gray-900 h-9 px-2 sm:px-3"
|
|
1019
|
+
:disabled="(isServerSide ? Number(serverMeta?.current_page) === Number(serverMeta?.last_page) : currentPage === totalPages)"
|
|
1020
|
+
@click="handlePageChange(isServerSide ? (Number(serverMeta?.current_page || 1)) + 1 : currentPage + 1)"
|
|
996
1021
|
>
|
|
997
1022
|
<span class="mr-1 hidden sm:inline">Next</span>
|
|
998
1023
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4"><path d="m9 18 6-6-6-6"/></svg>
|