vue-slottable 1.0.0 → 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 +203 -112
- package/dist/style.css +1 -1
- package/dist/vue-slottable.mjs +110 -38
- package/dist/vue-slottable.umd.js +1 -1
- package/package.json +4 -4
- package/src/App.vue +686 -103
- package/src/components/SlotTable.vue +120 -30
- package/src/components/SlotTableColumn.vue +12 -0
- package/src/types.d.ts +8 -0
package/README.md
CHANGED
|
@@ -1,22 +1,14 @@
|
|
|
1
1
|
# vue-slottable
|
|
2
2
|
|
|
3
|
-
[](https://github.com/muraliavarma/vue-slot-table/actions/workflows/ci.yml)
|
|
4
4
|
[](https://www.npmjs.com/package/vue-slottable)
|
|
5
5
|
[](./LICENSE.txt)
|
|
6
6
|
|
|
7
|
-
A flexible, slot-based Vue 3
|
|
7
|
+
A flexible, slot-based table component for Vue 3. Define columns with scoped slots, add sticky columns, column groups, sorting, and more — with zero CSS opinions.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
- **Slot-based columns** — define headers and cells with named slots
|
|
12
|
-
- **Sticky columns** — pin columns to the left or right edge
|
|
13
|
-
- **Column groups** — add grouped header rows with colspan
|
|
14
|
-
- **Row click events** — handle row interactions
|
|
15
|
-
- **Zero CSS opinions** — bring your own styles
|
|
16
|
-
- **Lightweight** — no dependencies beyond Vue 3
|
|
17
|
-
- **TypeScript declarations** included
|
|
9
|
+
**[Live Examples](https://muraliavarma.github.io/vue-slot-table/)**
|
|
18
10
|
|
|
19
|
-
##
|
|
11
|
+
## Install
|
|
20
12
|
|
|
21
13
|
```bash
|
|
22
14
|
npm install vue-slottable
|
|
@@ -30,132 +22,80 @@ Requires Vue 3.4+.
|
|
|
30
22
|
<script setup>
|
|
31
23
|
import { SlotTable, SlotTableColumn } from 'vue-slottable'
|
|
32
24
|
|
|
33
|
-
const
|
|
34
|
-
{ name: 'Alice',
|
|
35
|
-
{ name: 'Bob',
|
|
25
|
+
const users = [
|
|
26
|
+
{ name: 'Alice', role: 'Engineer' },
|
|
27
|
+
{ name: 'Bob', role: 'Designer' },
|
|
36
28
|
]
|
|
37
29
|
</script>
|
|
38
30
|
|
|
39
31
|
<template>
|
|
40
|
-
<SlotTable :rows="
|
|
32
|
+
<SlotTable :rows="users">
|
|
41
33
|
<SlotTableColumn>
|
|
42
34
|
<template #header>Name</template>
|
|
43
35
|
<template #cell="{ row }">{{ row.name }}</template>
|
|
44
36
|
</SlotTableColumn>
|
|
45
|
-
|
|
46
37
|
<SlotTableColumn>
|
|
47
|
-
<template #header>
|
|
48
|
-
<template #cell="{ row }">{{ row.
|
|
38
|
+
<template #header>Role</template>
|
|
39
|
+
<template #cell="{ row }">{{ row.role }}</template>
|
|
49
40
|
</SlotTableColumn>
|
|
50
41
|
</SlotTable>
|
|
51
42
|
</template>
|
|
52
43
|
```
|
|
53
44
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
### `<SlotTable>`
|
|
57
|
-
|
|
58
|
-
The main table component. Renders a `<table>` element.
|
|
59
|
-
|
|
60
|
-
#### Props
|
|
61
|
-
|
|
62
|
-
| Prop | Type | Required | Default | Description |
|
|
63
|
-
|------|------|----------|---------|-------------|
|
|
64
|
-
| `rows` | `Array` | Yes | — | Array of row data objects |
|
|
65
|
-
| `table-class` | `String` | No | `''` | CSS class applied to the `<table>` element |
|
|
66
|
-
|
|
67
|
-
#### Events
|
|
68
|
-
|
|
69
|
-
| Event | Payload | Description |
|
|
70
|
-
|-------|---------|-------------|
|
|
71
|
-
| `row-click` | `rowIndex: number` | Emitted when a table row is clicked |
|
|
72
|
-
|
|
73
|
-
#### Slots
|
|
74
|
-
|
|
75
|
-
| Slot | Description |
|
|
76
|
-
|------|-------------|
|
|
77
|
-
| `default` | Accepts `<SlotTableColumn>` and `<SlotTableColumnGroup>` children |
|
|
78
|
-
|
|
79
|
-
---
|
|
80
|
-
|
|
81
|
-
### `<SlotTableColumn>`
|
|
82
|
-
|
|
83
|
-
Defines a single table column. This is a renderless component — it must be a direct child of `<SlotTable>`.
|
|
84
|
-
|
|
85
|
-
#### Props
|
|
86
|
-
|
|
87
|
-
| Prop | Type | Default | Description |
|
|
88
|
-
|------|------|---------|-------------|
|
|
89
|
-
| `sticky` | `String` | `''` | Set to `'left'` or `'right'` to make the column sticky |
|
|
90
|
-
|
|
91
|
-
#### Slots
|
|
92
|
-
|
|
93
|
-
| Slot | Scope | Description |
|
|
94
|
-
|------|-------|-------------|
|
|
95
|
-
| `header` | — | Content for the column's `<th>` |
|
|
96
|
-
| `cell` | `{ row, rowIndex, columnIndex }` | Content for each `<td>` in this column |
|
|
97
|
-
|
|
98
|
-
---
|
|
99
|
-
|
|
100
|
-
### `<SlotTableColumnGroup>`
|
|
101
|
-
|
|
102
|
-
Defines a grouped header row entry. Must be a direct child of `<SlotTable>`.
|
|
103
|
-
|
|
104
|
-
#### Props
|
|
45
|
+
That's it. No configuration objects, no render props — just slots.
|
|
105
46
|
|
|
106
|
-
|
|
107
|
-
|------|------|---------|-------------|
|
|
108
|
-
| `sticky` | `String` | `''` | Set to `'left'` or `'right'` for sticky positioning |
|
|
109
|
-
| `colspan` | `Number` | — | Number of columns this group header spans |
|
|
47
|
+
## Features
|
|
110
48
|
|
|
111
|
-
|
|
49
|
+
### Custom Cell Rendering
|
|
112
50
|
|
|
113
|
-
|
|
114
|
-
|------|-------------|
|
|
115
|
-
| `default` | Content for the group `<th>` |
|
|
51
|
+
Put anything inside a cell — HTML, components, computed values:
|
|
116
52
|
|
|
117
|
-
|
|
53
|
+
```vue
|
|
54
|
+
<SlotTableColumn>
|
|
55
|
+
<template #header>Status</template>
|
|
56
|
+
<template #cell="{ row }">
|
|
57
|
+
<span :class="'badge-' + row.status">{{ row.status }}</span>
|
|
58
|
+
</template>
|
|
59
|
+
</SlotTableColumn>
|
|
60
|
+
```
|
|
118
61
|
|
|
119
62
|
### Sticky Columns
|
|
120
63
|
|
|
64
|
+
Pin columns to the left or right edge. They stay visible when scrolling horizontally:
|
|
65
|
+
|
|
121
66
|
```vue
|
|
122
|
-
<
|
|
123
|
-
<
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
</SlotTableColumn>
|
|
67
|
+
<SlotTableColumn sticky="left">
|
|
68
|
+
<template #header>Name</template>
|
|
69
|
+
<template #cell="{ row }">{{ row.name }}</template>
|
|
70
|
+
</SlotTableColumn>
|
|
127
71
|
|
|
128
|
-
|
|
129
|
-
<template #header>Description</template>
|
|
130
|
-
<template #cell="{ row }">{{ row.description }}</template>
|
|
131
|
-
</SlotTableColumn>
|
|
72
|
+
<!-- scrollable columns in the middle -->
|
|
132
73
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
</SlotTable>
|
|
74
|
+
<SlotTableColumn sticky="right">
|
|
75
|
+
<template #header>Actions</template>
|
|
76
|
+
<template #cell="{ row }">
|
|
77
|
+
<button @click.stop="edit(row)">Edit</button>
|
|
78
|
+
</template>
|
|
79
|
+
</SlotTableColumn>
|
|
140
80
|
```
|
|
141
81
|
|
|
142
82
|
### Column Groups
|
|
143
83
|
|
|
84
|
+
Add grouped header rows that span multiple columns:
|
|
85
|
+
|
|
144
86
|
```vue
|
|
145
|
-
<SlotTable :rows="
|
|
146
|
-
<SlotTableColumnGroup :colspan="2">Personal</SlotTableColumnGroup>
|
|
87
|
+
<SlotTable :rows="data">
|
|
88
|
+
<SlotTableColumnGroup :colspan="2">Personal Info</SlotTableColumnGroup>
|
|
147
89
|
<SlotTableColumnGroup :colspan="1">Work</SlotTableColumnGroup>
|
|
148
90
|
|
|
149
91
|
<SlotTableColumn>
|
|
150
92
|
<template #header>Name</template>
|
|
151
93
|
<template #cell="{ row }">{{ row.name }}</template>
|
|
152
94
|
</SlotTableColumn>
|
|
153
|
-
|
|
154
95
|
<SlotTableColumn>
|
|
155
96
|
<template #header>Age</template>
|
|
156
97
|
<template #cell="{ row }">{{ row.age }}</template>
|
|
157
98
|
</SlotTableColumn>
|
|
158
|
-
|
|
159
99
|
<SlotTableColumn>
|
|
160
100
|
<template #header>Role</template>
|
|
161
101
|
<template #cell="{ row }">{{ row.role }}</template>
|
|
@@ -163,41 +103,192 @@ Defines a grouped header row entry. Must be a direct child of `<SlotTable>`.
|
|
|
163
103
|
</SlotTable>
|
|
164
104
|
```
|
|
165
105
|
|
|
166
|
-
###
|
|
106
|
+
### Sorting (via header-click)
|
|
107
|
+
|
|
108
|
+
The component doesn't impose a sorting implementation — use `@header-click` to build your own:
|
|
167
109
|
|
|
168
110
|
```vue
|
|
169
111
|
<script setup>
|
|
170
|
-
|
|
171
|
-
|
|
112
|
+
import { ref, computed } from 'vue'
|
|
113
|
+
|
|
114
|
+
const sortCol = ref(null)
|
|
115
|
+
const sortDir = ref('asc')
|
|
116
|
+
|
|
117
|
+
function onHeaderClick(columnIndex) {
|
|
118
|
+
if (sortCol.value === columnIndex) {
|
|
119
|
+
sortDir.value = sortDir.value === 'asc' ? 'desc' : 'asc'
|
|
120
|
+
} else {
|
|
121
|
+
sortCol.value = columnIndex
|
|
122
|
+
sortDir.value = 'asc'
|
|
123
|
+
}
|
|
172
124
|
}
|
|
125
|
+
|
|
126
|
+
const sortedRows = computed(() => {
|
|
127
|
+
if (sortCol.value === null) return rows
|
|
128
|
+
// your sort logic here
|
|
129
|
+
})
|
|
173
130
|
</script>
|
|
174
131
|
|
|
175
132
|
<template>
|
|
176
|
-
<SlotTable :rows="
|
|
177
|
-
<!-- columns
|
|
133
|
+
<SlotTable :rows="sortedRows" @header-click="onHeaderClick">
|
|
134
|
+
<!-- columns -->
|
|
178
135
|
</SlotTable>
|
|
179
136
|
</template>
|
|
180
137
|
```
|
|
181
138
|
|
|
182
|
-
###
|
|
139
|
+
### Row Events & Dynamic Styling
|
|
140
|
+
|
|
141
|
+
Handle clicks and style rows conditionally:
|
|
183
142
|
|
|
184
143
|
```vue
|
|
185
|
-
<
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
144
|
+
<SlotTable
|
|
145
|
+
:rows="employees"
|
|
146
|
+
hoverable
|
|
147
|
+
:row-class="(row) => row.active ? '' : 'row-dimmed'"
|
|
148
|
+
@row-click="(index, row) => selected = row"
|
|
149
|
+
>
|
|
150
|
+
<!-- columns -->
|
|
151
|
+
</SlotTable>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Striped & Bordered
|
|
155
|
+
|
|
156
|
+
Classic table styles with boolean props:
|
|
157
|
+
|
|
158
|
+
```vue
|
|
159
|
+
<SlotTable :rows="data" striped bordered>
|
|
160
|
+
<!-- columns -->
|
|
161
|
+
</SlotTable>
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Column Width & Alignment
|
|
165
|
+
|
|
166
|
+
Control sizing and text alignment per column:
|
|
167
|
+
|
|
168
|
+
```vue
|
|
169
|
+
<SlotTableColumn width="80px" align="center">
|
|
170
|
+
<template #header>#</template>
|
|
171
|
+
<template #cell="{ rowIndex }">{{ rowIndex + 1 }}</template>
|
|
172
|
+
</SlotTableColumn>
|
|
173
|
+
|
|
174
|
+
<SlotTableColumn min-width="200px" align="right">
|
|
175
|
+
<template #header>Price</template>
|
|
176
|
+
<template #cell="{ row }">{{ formatPrice(row.price) }}</template>
|
|
190
177
|
</SlotTableColumn>
|
|
191
178
|
```
|
|
192
179
|
|
|
180
|
+
### Empty State
|
|
181
|
+
|
|
182
|
+
Show a custom message when there's no data:
|
|
183
|
+
|
|
184
|
+
```vue
|
|
185
|
+
<SlotTable :rows="filteredData">
|
|
186
|
+
<template #empty>
|
|
187
|
+
<p>No results found. Try a different search.</p>
|
|
188
|
+
</template>
|
|
189
|
+
|
|
190
|
+
<!-- columns still needed for headers -->
|
|
191
|
+
<SlotTableColumn>
|
|
192
|
+
<template #header>Name</template>
|
|
193
|
+
<template #cell="{ row }">{{ row.name }}</template>
|
|
194
|
+
</SlotTableColumn>
|
|
195
|
+
</SlotTable>
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Row Keys
|
|
199
|
+
|
|
200
|
+
For efficient rendering when rows change, provide a key:
|
|
201
|
+
|
|
202
|
+
```vue
|
|
203
|
+
<SlotTable :rows="data" row-key="id">
|
|
204
|
+
<!-- columns -->
|
|
205
|
+
</SlotTable>
|
|
206
|
+
|
|
207
|
+
<!-- or use a function -->
|
|
208
|
+
<SlotTable :rows="data" :row-key="(row) => row.id">
|
|
209
|
+
<!-- columns -->
|
|
210
|
+
</SlotTable>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## API Reference
|
|
216
|
+
|
|
217
|
+
### `<SlotTable>`
|
|
218
|
+
|
|
219
|
+
| Prop | Type | Default | Description |
|
|
220
|
+
|------|------|---------|-------------|
|
|
221
|
+
| `rows` | `Array` | *required* | Array of row data objects |
|
|
222
|
+
| `table-class` | `String` | `''` | CSS class on the `<table>` element |
|
|
223
|
+
| `row-key` | `String \| Function` | — | Key for each `<tr>` (field name or `(row, index) => key`) |
|
|
224
|
+
| `row-class` | `String \| Object \| Function` | — | Class for each `<tr>` (or `(row, index) => class`) |
|
|
225
|
+
| `striped` | `Boolean` | `false` | Alternating row backgrounds |
|
|
226
|
+
| `hoverable` | `Boolean` | `false` | Highlight rows on hover |
|
|
227
|
+
| `bordered` | `Boolean` | `false` | Add cell borders |
|
|
228
|
+
|
|
229
|
+
| Event | Payload | Description |
|
|
230
|
+
|-------|---------|-------------|
|
|
231
|
+
| `row-click` | `(rowIndex, row)` | Fired when a row is clicked |
|
|
232
|
+
| `header-click` | `(columnIndex)` | Fired when a header cell is clicked |
|
|
233
|
+
|
|
234
|
+
| Slot | Description |
|
|
235
|
+
|------|-------------|
|
|
236
|
+
| `default` | `<SlotTableColumn>` and `<SlotTableColumnGroup>` children |
|
|
237
|
+
| `empty` | Content shown when `rows` is empty |
|
|
238
|
+
|
|
239
|
+
### `<SlotTableColumn>`
|
|
240
|
+
|
|
241
|
+
Renderless component — must be a direct child of `<SlotTable>`.
|
|
242
|
+
|
|
243
|
+
| Prop | Type | Default | Description |
|
|
244
|
+
|------|------|---------|-------------|
|
|
245
|
+
| `sticky` | `String` | `''` | `'left'` or `'right'` |
|
|
246
|
+
| `align` | `String` | `''` | `'left'`, `'center'`, or `'right'` |
|
|
247
|
+
| `width` | `String` | `''` | CSS width (e.g. `'100px'`) |
|
|
248
|
+
| `min-width` | `String` | `''` | CSS min-width (e.g. `'200px'`) |
|
|
249
|
+
|
|
250
|
+
| Slot | Scope | Description |
|
|
251
|
+
|------|-------|-------------|
|
|
252
|
+
| `header` | — | Column header content (`<th>`) |
|
|
253
|
+
| `cell` | `{ row, rowIndex, columnIndex }` | Cell content (`<td>`) for each row |
|
|
254
|
+
|
|
255
|
+
### `<SlotTableColumnGroup>`
|
|
256
|
+
|
|
257
|
+
Renderless component for grouped header rows.
|
|
258
|
+
|
|
259
|
+
| Prop | Type | Default | Description |
|
|
260
|
+
|------|------|---------|-------------|
|
|
261
|
+
| `sticky` | `String` | `''` | `'left'` or `'right'` |
|
|
262
|
+
| `colspan` | `Number` | — | Number of columns to span |
|
|
263
|
+
|
|
264
|
+
| Slot | Description |
|
|
265
|
+
|------|-------------|
|
|
266
|
+
| `default` | Group header content |
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## CSS Classes
|
|
271
|
+
|
|
272
|
+
The component applies these classes that you can style:
|
|
273
|
+
|
|
274
|
+
| Class | Applied when |
|
|
275
|
+
|-------|-------------|
|
|
276
|
+
| `sticky-left` | Column has `sticky="left"` |
|
|
277
|
+
| `sticky-right` | Column has `sticky="right"` |
|
|
278
|
+
| `align-left` / `align-center` / `align-right` | Column has `align` prop |
|
|
279
|
+
| `slot-table-striped` | Odd rows when `striped` is true |
|
|
280
|
+
| `slot-table-hoverable` | All rows when `hoverable` is true |
|
|
281
|
+
| `slot-table-bordered` | Table element when `bordered` is true |
|
|
282
|
+
| `slot-table-empty` | The `<td>` wrapping the empty slot |
|
|
283
|
+
|
|
193
284
|
## Development
|
|
194
285
|
|
|
195
286
|
```bash
|
|
196
287
|
npm install
|
|
197
|
-
npm run dev #
|
|
288
|
+
npm run dev # Dev server with live examples
|
|
198
289
|
npm test # Run tests
|
|
199
290
|
npm run lint # Lint
|
|
200
|
-
npm run build:lib # Build library
|
|
291
|
+
npm run build:lib # Build library
|
|
201
292
|
```
|
|
202
293
|
|
|
203
294
|
## Contributing
|
package/dist/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.sticky-left{position:sticky;left:0}.sticky-right{position:sticky;right:0}
|
|
1
|
+
.sticky-left{position:sticky;left:0;z-index:1}.sticky-right{position:sticky;right:0;z-index:1}.align-left{text-align:left}.align-center{text-align:center}.align-right{text-align:right}
|
package/dist/vue-slottable.mjs
CHANGED
|
@@ -1,16 +1,28 @@
|
|
|
1
|
-
import { defineComponent as
|
|
2
|
-
const
|
|
1
|
+
import { defineComponent as b, h as i } from "vue";
|
|
2
|
+
const W = b({
|
|
3
3
|
name: "SlotTableColumn",
|
|
4
4
|
props: {
|
|
5
5
|
sticky: {
|
|
6
6
|
type: String,
|
|
7
7
|
default: ""
|
|
8
|
+
},
|
|
9
|
+
align: {
|
|
10
|
+
type: String,
|
|
11
|
+
default: ""
|
|
12
|
+
},
|
|
13
|
+
width: {
|
|
14
|
+
type: String,
|
|
15
|
+
default: ""
|
|
16
|
+
},
|
|
17
|
+
minWidth: {
|
|
18
|
+
type: String,
|
|
19
|
+
default: ""
|
|
8
20
|
}
|
|
9
21
|
},
|
|
10
22
|
setup() {
|
|
11
23
|
return () => null;
|
|
12
24
|
}
|
|
13
|
-
}),
|
|
25
|
+
}), B = b({
|
|
14
26
|
name: "SlotTableColumnGroup",
|
|
15
27
|
props: {
|
|
16
28
|
sticky: {
|
|
@@ -25,7 +37,7 @@ const w = i({
|
|
|
25
37
|
setup() {
|
|
26
38
|
return () => null;
|
|
27
39
|
}
|
|
28
|
-
}),
|
|
40
|
+
}), F = b({
|
|
29
41
|
name: "SlotTable",
|
|
30
42
|
props: {
|
|
31
43
|
rows: {
|
|
@@ -35,47 +47,107 @@ const w = i({
|
|
|
35
47
|
tableClass: {
|
|
36
48
|
type: String,
|
|
37
49
|
default: ""
|
|
50
|
+
},
|
|
51
|
+
rowKey: {
|
|
52
|
+
type: [String, Function],
|
|
53
|
+
default: void 0
|
|
54
|
+
},
|
|
55
|
+
rowClass: {
|
|
56
|
+
type: [String, Object, Function],
|
|
57
|
+
default: void 0
|
|
58
|
+
},
|
|
59
|
+
striped: {
|
|
60
|
+
type: Boolean,
|
|
61
|
+
default: !1
|
|
62
|
+
},
|
|
63
|
+
hoverable: {
|
|
64
|
+
type: Boolean,
|
|
65
|
+
default: !1
|
|
66
|
+
},
|
|
67
|
+
bordered: {
|
|
68
|
+
type: Boolean,
|
|
69
|
+
default: !1
|
|
38
70
|
}
|
|
39
71
|
},
|
|
40
|
-
emits: ["row-click"],
|
|
41
|
-
setup(
|
|
72
|
+
emits: ["row-click", "header-click"],
|
|
73
|
+
setup(e, { slots: y, emit: g }) {
|
|
74
|
+
function p(n) {
|
|
75
|
+
const t = {};
|
|
76
|
+
return n.width && (t.width = n.width), (n["min-width"] || n.minWidth) && (t.minWidth = n["min-width"] || n.minWidth), Object.keys(t).length > 0 ? t : void 0;
|
|
77
|
+
}
|
|
78
|
+
function C(n) {
|
|
79
|
+
const t = n.sticky || "", s = n.align || "";
|
|
80
|
+
return {
|
|
81
|
+
"sticky-left": t === "left",
|
|
82
|
+
"sticky-right": t === "right",
|
|
83
|
+
"align-left": s === "left",
|
|
84
|
+
"align-center": s === "center",
|
|
85
|
+
"align-right": s === "right"
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function S(n, t) {
|
|
89
|
+
return e.rowKey ? typeof e.rowKey == "function" ? e.rowKey(n, t) : n[e.rowKey] : t;
|
|
90
|
+
}
|
|
91
|
+
function K(n, t) {
|
|
92
|
+
const s = {};
|
|
93
|
+
if (e.striped && t % 2 === 1 && (s["slot-table-striped"] = !0), e.hoverable && (s["slot-table-hoverable"] = !0), !e.rowClass) return s;
|
|
94
|
+
if (typeof e.rowClass == "function") {
|
|
95
|
+
const u = e.rowClass(n, t);
|
|
96
|
+
typeof u == "string" ? s[u] = !0 : typeof u == "object" && Object.assign(s, u);
|
|
97
|
+
} else typeof e.rowClass == "string" ? s[e.rowClass] = !0 : Object.assign(s, e.rowClass);
|
|
98
|
+
return s;
|
|
99
|
+
}
|
|
42
100
|
return () => {
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
101
|
+
const n = y.default ? y.default() : [], t = [], s = [];
|
|
102
|
+
n.forEach((l) => {
|
|
103
|
+
l.type === W ? t.push(l) : l.type === B && s.push(l);
|
|
46
104
|
});
|
|
47
|
-
const
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
"sticky-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
105
|
+
const u = t.map((l, a) => {
|
|
106
|
+
const c = l.props || {}, d = C(c), o = p(c), r = l.children && l.children.header, f = typeof r == "function" ? r() : null;
|
|
107
|
+
return i("th", {
|
|
108
|
+
class: d,
|
|
109
|
+
style: o,
|
|
110
|
+
onClick: () => g("header-click", a)
|
|
111
|
+
}, f);
|
|
112
|
+
}), w = s.map((l) => {
|
|
113
|
+
const a = l.props || {}, c = a.sticky || "", d = a.colspan ? Number(a.colspan) : void 0, o = {
|
|
114
|
+
"sticky-left": c === "left",
|
|
115
|
+
"sticky-right": c === "right"
|
|
116
|
+
}, r = l.children && l.children.default, f = typeof r == "function" ? r() : null;
|
|
117
|
+
return i("th", { class: o, colspan: d }, f);
|
|
118
|
+
}), h = [];
|
|
119
|
+
w.length > 0 && h.push(i("tr", null, w)), h.push(i("tr", null, u));
|
|
120
|
+
const T = i("thead", null, h);
|
|
121
|
+
let m;
|
|
122
|
+
if (e.rows.length === 0 && y.empty) {
|
|
123
|
+
const l = i("tr", null, [
|
|
124
|
+
i("td", { colspan: t.length, class: "slot-table-empty" }, y.empty())
|
|
125
|
+
]);
|
|
126
|
+
m = i("tbody", null, [l]);
|
|
127
|
+
} else {
|
|
128
|
+
const l = e.rows.map((a, c) => {
|
|
129
|
+
const d = t.map((o, r) => {
|
|
130
|
+
const f = o.props || {}, j = C(f), R = p(f), k = o.children && o.children.cell, O = typeof k == "function" ? k({ row: a, rowIndex: c, columnIndex: r }) : null;
|
|
131
|
+
return i("td", { class: j, style: R }, O);
|
|
132
|
+
});
|
|
133
|
+
return i("tr", {
|
|
134
|
+
key: S(a, c),
|
|
135
|
+
class: K(a, c),
|
|
136
|
+
onClick: () => g("row-click", c, a)
|
|
137
|
+
}, d);
|
|
68
138
|
});
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
139
|
+
m = i("tbody", null, l);
|
|
140
|
+
}
|
|
141
|
+
const _ = {
|
|
142
|
+
[e.tableClass]: !!e.tableClass,
|
|
143
|
+
"slot-table-bordered": e.bordered
|
|
144
|
+
};
|
|
145
|
+
return i("table", { class: _ }, [T, m]);
|
|
74
146
|
};
|
|
75
147
|
}
|
|
76
148
|
});
|
|
77
149
|
export {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
150
|
+
F as SlotTable,
|
|
151
|
+
W as SlotTableColumn,
|
|
152
|
+
B as SlotTableColumnGroup
|
|
81
153
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(a,t){typeof exports=="object"&&typeof module<"u"?t(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],t):(a=typeof globalThis<"u"?globalThis:a||self,t(a.VueSlotTable={},a.Vue))})(this,function(a,t){"use strict";const p=t.defineComponent({name:"SlotTableColumn",props:{sticky:{type:String,default:""},align:{type:String,default:""},width:{type:String,default:""},minWidth:{type:String,default:""}},setup(){return()=>null}}),g=t.defineComponent({name:"SlotTableColumnGroup",props:{sticky:{type:String,default:""},colspan:{type:Number,default:void 0}},setup(){return()=>null}}),j=t.defineComponent({name:"SlotTable",props:{rows:{type:Array,required:!0},tableClass:{type:String,default:""},rowKey:{type:[String,Function],default:void 0},rowClass:{type:[String,Object,Function],default:void 0},striped:{type:Boolean,default:!1},hoverable:{type:Boolean,default:!1},bordered:{type:Boolean,default:!1}},emits:["row-click","header-click"],setup(n,{slots:y,emit:C}){function S(l){const e={};return l.width&&(e.width=l.width),(l["min-width"]||l.minWidth)&&(e.minWidth=l["min-width"]||l.minWidth),Object.keys(e).length>0?e:void 0}function w(l){const e=l.sticky||"",i=l.align||"";return{"sticky-left":e==="left","sticky-right":e==="right","align-left":i==="left","align-center":i==="center","align-right":i==="right"}}function K(l,e){return n.rowKey?typeof n.rowKey=="function"?n.rowKey(l,e):l[n.rowKey]:e}function _(l,e){const i={};if(n.striped&&e%2===1&&(i["slot-table-striped"]=!0),n.hoverable&&(i["slot-table-hoverable"]=!0),!n.rowClass)return i;if(typeof n.rowClass=="function"){const f=n.rowClass(l,e);typeof f=="string"?i[f]=!0:typeof f=="object"&&Object.assign(i,f)}else typeof n.rowClass=="string"?i[n.rowClass]=!0:Object.assign(i,n.rowClass);return i}return()=>{const l=y.default?y.default():[],e=[],i=[];l.forEach(s=>{s.type===p?e.push(s):s.type===g&&i.push(s)});const f=e.map((s,o)=>{const c=s.props||{},h=w(c),r=S(c),u=s.children&&s.children.header,d=typeof u=="function"?u():null;return t.h("th",{class:h,style:r,onClick:()=>C("header-click",o)},d)}),k=i.map(s=>{const o=s.props||{},c=o.sticky||"",h=o.colspan?Number(o.colspan):void 0,r={"sticky-left":c==="left","sticky-right":c==="right"},u=s.children&&s.children.default,d=typeof u=="function"?u():null;return t.h("th",{class:r,colspan:h},d)}),m=[];k.length>0&&m.push(t.h("tr",null,k)),m.push(t.h("tr",null,f));const O=t.h("thead",null,m);let b;if(n.rows.length===0&&y.empty){const s=t.h("tr",null,[t.h("td",{colspan:e.length,class:"slot-table-empty"},y.empty())]);b=t.h("tbody",null,[s])}else{const s=n.rows.map((o,c)=>{const h=e.map((r,u)=>{const d=r.props||{},W=w(d),B=S(d),T=r.children&&r.children.cell,G=typeof T=="function"?T({row:o,rowIndex:c,columnIndex:u}):null;return t.h("td",{class:W,style:B},G)});return t.h("tr",{key:K(o,c),class:_(o,c),onClick:()=>C("row-click",c,o)},h)});b=t.h("tbody",null,s)}const R={[n.tableClass]:!!n.tableClass,"slot-table-bordered":n.bordered};return t.h("table",{class:R},[O,b])}}});a.SlotTable=j,a.SlotTableColumn=p,a.SlotTableColumnGroup=g,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vue-slottable",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "A flexible, slot-based Vue 3 table component with sticky columns, column groups, and scoped slots for custom cell rendering.",
|
|
5
5
|
"main": "./dist/vue-slottable.umd.js",
|
|
6
6
|
"module": "./dist/vue-slottable.mjs",
|
|
@@ -53,10 +53,10 @@
|
|
|
53
53
|
"license": "MIT",
|
|
54
54
|
"repository": {
|
|
55
55
|
"type": "git",
|
|
56
|
-
"url": "git+https://github.com/
|
|
56
|
+
"url": "git+https://github.com/muraliavarma/vue-slot-table.git"
|
|
57
57
|
},
|
|
58
|
-
"homepage": "https://github.com/
|
|
58
|
+
"homepage": "https://github.com/muraliavarma/vue-slot-table#readme",
|
|
59
59
|
"bugs": {
|
|
60
|
-
"url": "https://github.com/
|
|
60
|
+
"url": "https://github.com/muraliavarma/vue-slot-table/issues"
|
|
61
61
|
}
|
|
62
62
|
}
|