@kikiloaw/simple-table 1.0.5 → 1.1.0
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
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
[](https://vuejs.org/)
|
|
7
7
|
[](https://www.typescriptlang.org/)
|
|
8
8
|
|
|
9
|
+
> **🚀 Explore the Demo**: Check out the [SimpleTable Demo Repository](https://github.com/kikiloaw/simple-table-demo.git) for a complete documentation site with live server-side examples, seeding, and source code.
|
|
10
|
+
|
|
9
11
|
---
|
|
10
12
|
|
|
11
13
|
## ✨ Why SimpleTable?
|
|
@@ -475,7 +477,7 @@ SimpleTable supports three data modes:
|
|
|
475
477
|
label: 'Name', // Required: Column header text
|
|
476
478
|
sortable: true, // Optional: Enable sorting
|
|
477
479
|
width: '200px', // Optional: Fixed column width
|
|
478
|
-
fixed: true, // Optional: Sticky column (
|
|
480
|
+
fixed: true, // Optional: Sticky column (left for first, right for last, others left). **Requires `width` to be set.**
|
|
479
481
|
class: 'text-center' // Optional: Additional CSS classes
|
|
480
482
|
}
|
|
481
483
|
```
|
package/package.json
CHANGED
package/src/SimpleTable.vue
CHANGED
|
@@ -67,6 +67,8 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
67
67
|
hoverColor: 'hover:bg-stone-200'
|
|
68
68
|
})
|
|
69
69
|
|
|
70
|
+
|
|
71
|
+
|
|
70
72
|
// ...
|
|
71
73
|
|
|
72
74
|
// -- Computed: Page Sizes Normalization --
|
|
@@ -163,7 +165,7 @@ const densityConfig = computed(() => {
|
|
|
163
165
|
</div>
|
|
164
166
|
*/
|
|
165
167
|
|
|
166
|
-
const emit = defineEmits(['update:search', 'update:sort', 'page-change'])
|
|
168
|
+
const emit = defineEmits(['update:search', 'update:sort', 'page-change', 'fetched'])
|
|
167
169
|
|
|
168
170
|
// -- State --
|
|
169
171
|
const searchQuery = ref('')
|
|
@@ -464,6 +466,7 @@ async function fetchData(params: any = {}) {
|
|
|
464
466
|
}
|
|
465
467
|
|
|
466
468
|
internalData.value = data
|
|
469
|
+
emit('fetched', data)
|
|
467
470
|
|
|
468
471
|
// Store in cache if enabled
|
|
469
472
|
if (props.enableCache) {
|
|
@@ -644,6 +647,8 @@ defineExpose({
|
|
|
644
647
|
clearCache // expose cache clearing method
|
|
645
648
|
})
|
|
646
649
|
|
|
650
|
+
|
|
651
|
+
|
|
647
652
|
// -- Helper Styles --
|
|
648
653
|
function getCellClass(col: any, index: number, totalCols: number, rowIndex: number = -1) {
|
|
649
654
|
let classes = col.class || ''
|
|
@@ -653,15 +658,13 @@ function getCellClass(col: any, index: number, totalCols: number, rowIndex: numb
|
|
|
653
658
|
|
|
654
659
|
if (col.fixed) {
|
|
655
660
|
// Sticky logic
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
// Right sticky: Stronger shadow to the left, and a left border
|
|
661
|
-
stickyClass = ' sticky right-0 z-10 shadow-[-4px_0_8px_-2px_rgba(0,0,0,0.1)] border-l border-border/50'
|
|
661
|
+
let stickyClass = ' whitespace-nowrap' // Prevent content wrapping in sticky columns
|
|
662
|
+
if (index === totalCols - 1) {
|
|
663
|
+
// Last Column -> Right Sticky
|
|
664
|
+
stickyClass = ' sticky right-0 z-10 shadow-[-4px_0_8px_-2px_rgba(0,0,0,0.1)] border-l border-stone-300'
|
|
662
665
|
} else {
|
|
663
|
-
//
|
|
664
|
-
stickyClass = ' sticky left-0 z-10 shadow-[4px_0_8px_-2px_rgba(0,0,0,0.1)] border-r border-
|
|
666
|
+
// All other fixed columns -> Left Sticky
|
|
667
|
+
stickyClass = ' sticky left-0 z-10 shadow-[4px_0_8px_-2px_rgba(0,0,0,0.1)] border-r border-stone-300'
|
|
665
668
|
}
|
|
666
669
|
|
|
667
670
|
// Determine background
|
|
@@ -670,8 +673,8 @@ function getCellClass(col: any, index: number, totalCols: number, rowIndex: numb
|
|
|
670
673
|
|
|
671
674
|
if (rowIndex !== -1) {
|
|
672
675
|
// Body Row
|
|
673
|
-
const
|
|
674
|
-
bgClass =
|
|
676
|
+
const isOdd = rowIndex % 2 === 0
|
|
677
|
+
bgClass = isOdd ? props.oddRowColor : props.evenRowColor
|
|
675
678
|
|
|
676
679
|
// Should also match hover
|
|
677
680
|
// If the row has a hover class (like hover:bg-muted), the sticky cell needs group-hover:bg-muted to match.
|
|
@@ -702,6 +705,10 @@ function getCellStyle(col: any) {
|
|
|
702
705
|
if (col.width) {
|
|
703
706
|
return { width: col.width, minWidth: col.width, maxWidth: col.width }
|
|
704
707
|
}
|
|
708
|
+
// Smart default: If fixed but no width, force a safe width (e.g. 100px) to ensure background covers content
|
|
709
|
+
if (col.fixed) {
|
|
710
|
+
return { width: '100px', minWidth: '100px' }
|
|
711
|
+
}
|
|
705
712
|
return {}
|
|
706
713
|
}
|
|
707
714
|
|
|
@@ -753,7 +760,7 @@ function getCellStyle(col: any) {
|
|
|
753
760
|
<!-- Table -->
|
|
754
761
|
<div class="border bg-background overflow-x-auto relative">
|
|
755
762
|
<!-- We add min-w-full to Table to ensure it stretches -->
|
|
756
|
-
<Table class="min-w-full table-
|
|
763
|
+
<Table class="min-w-full table-auto">
|
|
757
764
|
<TableHeader>
|
|
758
765
|
<TableRow :style="{ height: densityConfig.cellHeight }">
|
|
759
766
|
<TableHead
|
|
@@ -797,7 +804,12 @@ function getCellStyle(col: any) {
|
|
|
797
804
|
<!-- Group Header Row: Single cell spanning all columns -->
|
|
798
805
|
<template v-if="row._isGroupHeader">
|
|
799
806
|
<TableCell :colspan="columns.length" class="border-b border-gray-200">
|
|
800
|
-
<div :class="[
|
|
807
|
+
<div :class="[
|
|
808
|
+
'px-2',
|
|
809
|
+
densityConfig.groupHeaderPadding,
|
|
810
|
+
'font-semibold text-sm uppercase tracking-wide',
|
|
811
|
+
row._groupTitleClass || 'text-gray-700'
|
|
812
|
+
]">
|
|
801
813
|
{{ row._groupTitle }}
|
|
802
814
|
</div>
|
|
803
815
|
</TableCell>
|
|
@@ -16,7 +16,7 @@ const delegatedProps = computed(() => {
|
|
|
16
16
|
<template>
|
|
17
17
|
<div class="relative w-full overflow-auto">
|
|
18
18
|
<table
|
|
19
|
-
:class="cn('w-full caption-bottom text-sm', props.class)"
|
|
19
|
+
:class="cn('w-full caption-bottom text-sm border-separate border-spacing-0', props.class)"
|
|
20
20
|
v-bind="delegatedProps"
|
|
21
21
|
>
|
|
22
22
|
<slot />
|
|
@@ -7,6 +7,7 @@ const props = defineProps<{
|
|
|
7
7
|
style?: any
|
|
8
8
|
padding?: string
|
|
9
9
|
height?: string
|
|
10
|
+
colspan?: number | string
|
|
10
11
|
}>()
|
|
11
12
|
|
|
12
13
|
const delegatedProps = computed(() => {
|
|
@@ -25,7 +26,7 @@ const cellStyle = computed(() => {
|
|
|
25
26
|
|
|
26
27
|
<template>
|
|
27
28
|
<td
|
|
28
|
-
:class="cn(props.padding || 'p-2', 'align-middle [&:has([role=checkbox])]:pr-0', props.class)"
|
|
29
|
+
:class="cn(props.padding || 'p-2', 'border-b border-stone-300 align-middle [&:has([role=checkbox])]:pr-0', props.class)"
|
|
29
30
|
:style="cellStyle"
|
|
30
31
|
v-bind="delegatedProps"
|
|
31
32
|
>
|
|
@@ -21,7 +21,7 @@ const delegatedProps = computed(() => {
|
|
|
21
21
|
cn(
|
|
22
22
|
props.height || 'h-[38px]',
|
|
23
23
|
props.padding || 'px-2',
|
|
24
|
-
'text-left align-middle font-bold text-muted-foreground [&:has([role=checkbox])]:pr-0',
|
|
24
|
+
'border-b border-stone-300 text-left align-middle font-bold text-muted-foreground [&:has([role=checkbox])]:pr-0',
|
|
25
25
|
props.class,
|
|
26
26
|
)
|
|
27
27
|
"
|
|
@@ -17,7 +17,7 @@ const delegatedProps = computed(() => {
|
|
|
17
17
|
<tr
|
|
18
18
|
:class="
|
|
19
19
|
cn(
|
|
20
|
-
'
|
|
20
|
+
'transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted',
|
|
21
21
|
props.class,
|
|
22
22
|
)
|
|
23
23
|
"
|