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 CHANGED
@@ -1,22 +1,14 @@
1
1
  # vue-slottable
2
2
 
3
- [![CI](https://github.com/nickvdyck/vue-slot-table/actions/workflows/ci.yml/badge.svg)](https://github.com/nickvdyck/vue-slot-table/actions/workflows/ci.yml)
3
+ [![CI](https://github.com/muraliavarma/vue-slot-table/actions/workflows/ci.yml/badge.svg)](https://github.com/muraliavarma/vue-slot-table/actions/workflows/ci.yml)
4
4
  [![npm version](https://img.shields.io/npm/v/vue-slottable.svg)](https://www.npmjs.com/package/vue-slottable)
5
5
  [![license](https://img.shields.io/npm/l/vue-slottable.svg)](./LICENSE.txt)
6
6
 
7
- A flexible, slot-based Vue 3 table component with sticky columns, column groups, and scoped slots for custom cell rendering.
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
- ## Features
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
- ## Installation
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 rows = [
34
- { name: 'Alice', age: 28 },
35
- { name: 'Bob', age: 34 },
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="rows" table-class="my-table">
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>Age</template>
48
- <template #cell="{ row }">{{ row.age }}</template>
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
- ## API Reference
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
- | Prop | Type | Default | Description |
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
- #### Slots
49
+ ### Custom Cell Rendering
112
50
 
113
- | Slot | Description |
114
- |------|-------------|
115
- | `default` | Content for the group `<th>` |
51
+ Put anything inside a cell — HTML, components, computed values:
116
52
 
117
- ## Examples
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
- <SlotTable :rows="rows">
123
- <SlotTableColumn sticky="left">
124
- <template #header>ID</template>
125
- <template #cell="{ row }">{{ row.id }}</template>
126
- </SlotTableColumn>
67
+ <SlotTableColumn sticky="left">
68
+ <template #header>Name</template>
69
+ <template #cell="{ row }">{{ row.name }}</template>
70
+ </SlotTableColumn>
127
71
 
128
- <SlotTableColumn>
129
- <template #header>Description</template>
130
- <template #cell="{ row }">{{ row.description }}</template>
131
- </SlotTableColumn>
72
+ <!-- scrollable columns in the middle -->
132
73
 
133
- <SlotTableColumn sticky="right">
134
- <template #header>Actions</template>
135
- <template #cell="{ row }">
136
- <button @click.stop="edit(row)">Edit</button>
137
- </template>
138
- </SlotTableColumn>
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="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
- ### Row Click Events
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
- function onRowClick(rowIndex) {
171
- console.log('Clicked row:', rowIndex)
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="rows" @row-click="onRowClick">
177
- <!-- columns... -->
133
+ <SlotTable :rows="sortedRows" @header-click="onHeaderClick">
134
+ <!-- columns -->
178
135
  </SlotTable>
179
136
  </template>
180
137
  ```
181
138
 
182
- ### Custom Cell Rendering
139
+ ### Row Events & Dynamic Styling
140
+
141
+ Handle clicks and style rows conditionally:
183
142
 
184
143
  ```vue
185
- <SlotTableColumn>
186
- <template #header>Status</template>
187
- <template #cell="{ row }">
188
- <span :class="'badge-' + row.status">{{ row.status }}</span>
189
- </template>
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 # Start dev server with demo app
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 bundles
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}
@@ -1,16 +1,28 @@
1
- import { defineComponent as i, h as s } from "vue";
2
- const w = i({
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
- }), P = i({
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
- }), N = i({
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(p, { slots: f, emit: m }) {
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 k = f.default ? f.default() : [], a = [], d = [];
44
- k.forEach((t) => {
45
- t.type === w ? a.push(t) : t.type === P && d.push(t);
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 b = a.map((t) => {
48
- const l = (t.props || {}).sticky || "", n = {
49
- "sticky-left": l === "left",
50
- "sticky-right": l === "right"
51
- }, o = t.children && t.children.header, c = typeof o == "function" ? o() : null;
52
- return s("th", { class: n }, c);
53
- }), h = d.map((t) => {
54
- const e = t.props || {}, l = e.sticky || "", n = e.colspan ? Number(e.colspan) : void 0, o = {
55
- "sticky-left": l === "left",
56
- "sticky-right": l === "right"
57
- }, c = t.children && t.children.default, r = typeof c == "function" ? c() : null;
58
- return s("th", { class: o, colspan: n }, r);
59
- }), u = [];
60
- h.length > 0 && u.push(s("tr", null, h)), u.push(s("tr", null, b));
61
- const C = s("thead", null, u), S = p.rows.map((t, e) => {
62
- const l = a.map((n, o) => {
63
- const r = (n.props || {}).sticky || "", T = {
64
- "sticky-left": r === "left",
65
- "sticky-right": r === "right"
66
- }, y = n.children && n.children.cell, _ = typeof y == "function" ? y({ row: t, rowIndex: e, columnIndex: o }) : null;
67
- return s("td", { class: T }, _);
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
- return s("tr", {
70
- onClick: () => m("row-click", e)
71
- }, l);
72
- }), g = s("tbody", null, S);
73
- return s("table", { class: p.tableClass }, [C, g]);
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
- N as SlotTable,
79
- w as SlotTableColumn,
80
- P as SlotTableColumnGroup
150
+ F as SlotTable,
151
+ W as SlotTableColumn,
152
+ B as SlotTableColumnGroup
81
153
  };
@@ -1 +1 @@
1
- (function(n,t){typeof exports=="object"&&typeof module<"u"?t(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],t):(n=typeof globalThis<"u"?globalThis:n||self,t(n.VueSlotTable={},n.Vue))})(this,function(n,t){"use strict";const p=t.defineComponent({name:"SlotTableColumn",props:{sticky:{type:String,default:""}},setup(){return()=>null}}),f=t.defineComponent({name:"SlotTableColumnGroup",props:{sticky:{type:String,default:""},colspan:{type:Number,default:void 0}},setup(){return()=>null}}),k=t.defineComponent({name:"SlotTable",props:{rows:{type:Array,required:!0},tableClass:{type:String,default:""}},emits:["row-click"],setup(d,{slots:h,emit:S}){return()=>{const C=h.default?h.default():[],u=[],y=[];C.forEach(e=>{e.type===p?u.push(e):e.type===f&&y.push(e)});const g=u.map(e=>{const l=(e.props||{}).sticky||"",o={"sticky-left":l==="left","sticky-right":l==="right"},c=e.children&&e.children.header,r=typeof c=="function"?c():null;return t.h("th",{class:o},r)}),m=y.map(e=>{const s=e.props||{},l=s.sticky||"",o=s.colspan?Number(s.colspan):void 0,c={"sticky-left":l==="left","sticky-right":l==="right"},r=e.children&&e.children.default,i=typeof r=="function"?r():null;return t.h("th",{class:c,colspan:o},i)}),a=[];m.length>0&&a.push(t.h("tr",null,m)),a.push(t.h("tr",null,g));const T=t.h("thead",null,a),P=d.rows.map((e,s)=>{const l=u.map((o,c)=>{const i=(o.props||{}).sticky||"",w={"sticky-left":i==="left","sticky-right":i==="right"},b=o.children&&o.children.cell,G=typeof b=="function"?b({row:e,rowIndex:s,columnIndex:c}):null;return t.h("td",{class:w},G)});return t.h("tr",{onClick:()=>S("row-click",s)},l)}),_=t.h("tbody",null,P);return t.h("table",{class:d.tableClass},[T,_])}}});n.SlotTable=k,n.SlotTableColumn=p,n.SlotTableColumnGroup=f,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})});
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.0.0",
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/nickvdyck/vue-slot-table.git"
56
+ "url": "git+https://github.com/muraliavarma/vue-slot-table.git"
57
57
  },
58
- "homepage": "https://github.com/nickvdyck/vue-slot-table#readme",
58
+ "homepage": "https://github.com/muraliavarma/vue-slot-table#readme",
59
59
  "bugs": {
60
- "url": "https://github.com/nickvdyck/vue-slot-table/issues"
60
+ "url": "https://github.com/muraliavarma/vue-slot-table/issues"
61
61
  }
62
62
  }