tablevu 0.3.0-beta.2 → 0.3.0-beta.3
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/dist/array.d.ts +1 -1
- package/dist/table.d.ts +2 -123
- package/dist/tablevu-index.esm.js +91 -64
- package/dist/tablevu-index.umd.cjs.js +90 -64
- package/dist/tablevu-table.esm.js +91 -64
- package/dist/tablevu-table.umd.cjs.js +90 -64
- package/dist/types/adapter.d.ts +15 -0
- package/dist/types/index.d.ts +11 -0
- package/dist/types/tablevu-column.d.ts +22 -0
- package/dist/types/tablevu-emits.d.ts +8 -0
- package/dist/types/tablevu-footer-settings.d.ts +5 -0
- package/dist/types/tablevu-group.d.ts +6 -0
- package/dist/types/tablevu-page-settings.d.ts +4 -0
- package/dist/types/tablevu-props.d.ts +13 -0
- package/dist/types/tablevu-settings.d.ts +26 -0
- package/dist/types/tablevu-sort.d.ts +5 -0
- package/dist/types/tablevu-spec.d.ts +31 -0
- package/dist/types/tablevu-status.d.ts +6 -0
- package/package.json +1 -1
|
@@ -85,6 +85,7 @@
|
|
|
85
85
|
Ready: 0,
|
|
86
86
|
Loading: 1
|
|
87
87
|
};
|
|
88
|
+
|
|
88
89
|
const tablevu = {
|
|
89
90
|
props: {
|
|
90
91
|
settings: { type: Object, default: null },
|
|
@@ -92,14 +93,13 @@
|
|
|
92
93
|
group: { type: [String, Object] },
|
|
93
94
|
search: { type: String },
|
|
94
95
|
filter: { type: [Array, Object] },
|
|
95
|
-
command: { type: Array, default: () => [] },
|
|
96
96
|
rowid: { type: String },
|
|
97
97
|
onRowClick: { type: Function },
|
|
98
98
|
onRowDblClick: { type: Function },
|
|
99
99
|
class: { type: String, default: 'table' },
|
|
100
100
|
style: { type: String, default: null }
|
|
101
101
|
},
|
|
102
|
-
emits: ['onRowClick', 'onRowDblClick'],
|
|
102
|
+
emits: ['onRowClick', 'onRowDblClick', 'selectionChange', 'columnVisibilityChange'],
|
|
103
103
|
setup(props, { attrs, slots, emit, expose }) {
|
|
104
104
|
let rows = [];
|
|
105
105
|
let rowg = [];
|
|
@@ -109,16 +109,16 @@
|
|
|
109
109
|
const spec = vue.reactive({
|
|
110
110
|
caption: null,
|
|
111
111
|
group: {
|
|
112
|
-
value: (props.settings && props.settings.group) ? props.settings.group.value : props.group ? props.group :
|
|
113
|
-
content: (props.settings && props.settings.group) ? props.settings.group.content :
|
|
112
|
+
value: (props.settings && props.settings.group) ? props.settings.group.value : props.group ? props.group : undefined,
|
|
113
|
+
content: (props.settings && props.settings.group) ? props.settings.group.content : undefined,
|
|
114
114
|
expandAll: true,
|
|
115
115
|
class: 'table-light'
|
|
116
116
|
},
|
|
117
117
|
page: {
|
|
118
118
|
count: 0,
|
|
119
|
-
size: (props.settings && props.settings.page) ? props.settings.page.size : 0,
|
|
119
|
+
size: (props.settings && props.settings.page) ? (props.settings.page.size || 0) : 0,
|
|
120
120
|
current: 0,
|
|
121
|
-
type:
|
|
121
|
+
type: undefined
|
|
122
122
|
},
|
|
123
123
|
sort: (props.settings && props.settings.sort) ? props.settings.sort : [],
|
|
124
124
|
columns: (props.settings && props.settings.columns) ? props.settings.columns : [],
|
|
@@ -131,7 +131,11 @@
|
|
|
131
131
|
time: null,
|
|
132
132
|
search: null,
|
|
133
133
|
filter: null,
|
|
134
|
-
onData: (props.settings && props.settings.onData) ? props.settings.onData : undefined
|
|
134
|
+
onData: (props.settings && props.settings.onData) ? props.settings.onData : undefined,
|
|
135
|
+
selectedRows: [],
|
|
136
|
+
columnWidths: {},
|
|
137
|
+
columnOrder: [],
|
|
138
|
+
columnVisibility: {}
|
|
135
139
|
});
|
|
136
140
|
if (props.data) {
|
|
137
141
|
if (Array.isArray(props.data)) {
|
|
@@ -167,32 +171,6 @@
|
|
|
167
171
|
spec.filter = null;
|
|
168
172
|
refresh();
|
|
169
173
|
}, { deep: true });
|
|
170
|
-
vue.watch(() => props.command, (n, o) => {
|
|
171
|
-
if (n && n.length > 0) {
|
|
172
|
-
const c = props.command[n.length - 1];
|
|
173
|
-
if (c && c.name) {
|
|
174
|
-
switch (c.name.toLowerCase()) {
|
|
175
|
-
case 'refresh':
|
|
176
|
-
refresh();
|
|
177
|
-
break;
|
|
178
|
-
case 'first':
|
|
179
|
-
first();
|
|
180
|
-
break;
|
|
181
|
-
case 'prior':
|
|
182
|
-
prior();
|
|
183
|
-
break;
|
|
184
|
-
case 'next':
|
|
185
|
-
next();
|
|
186
|
-
break;
|
|
187
|
-
case 'last':
|
|
188
|
-
last();
|
|
189
|
-
break;
|
|
190
|
-
default: console.log('Unknown command');
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
props.command.length = 0;
|
|
194
|
-
}
|
|
195
|
-
}, { deep: true });
|
|
196
174
|
function prepareGroup(g, r) {
|
|
197
175
|
grps = [];
|
|
198
176
|
rowg = [];
|
|
@@ -231,28 +209,26 @@
|
|
|
231
209
|
rowg.push(n);
|
|
232
210
|
}
|
|
233
211
|
}
|
|
234
|
-
function first() {
|
|
212
|
+
function first() { loadPage(1); }
|
|
235
213
|
function prior() {
|
|
236
214
|
if (spec.page.current > 1) {
|
|
237
|
-
|
|
215
|
+
loadPage(spec.page.current - 1);
|
|
238
216
|
}
|
|
239
217
|
else {
|
|
240
|
-
|
|
218
|
+
loadPage(spec.page.current);
|
|
241
219
|
}
|
|
242
220
|
}
|
|
243
|
-
function next() {
|
|
244
|
-
function last() {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
if (g && g > 0 && g != spec.page.current)
|
|
253
|
-
page(g);
|
|
221
|
+
function next() { loadPage(spec.page.current + 1); }
|
|
222
|
+
function last() { loadPage(spec.page.count); }
|
|
223
|
+
// Navigate to specific page number
|
|
224
|
+
function page(currentPage) {
|
|
225
|
+
if (currentPage < 1)
|
|
226
|
+
currentPage = 1;
|
|
227
|
+
if (currentPage > spec.page.count && spec.page.count > 0)
|
|
228
|
+
currentPage = spec.page.count;
|
|
229
|
+
loadPage(currentPage);
|
|
254
230
|
}
|
|
255
|
-
function refresh() {
|
|
231
|
+
function refresh() { loadPage(spec.page.current); }
|
|
256
232
|
function orderby(ind, dir) {
|
|
257
233
|
if (spec.sort && spec.sort.length > 0) {
|
|
258
234
|
let l = spec.sort.findIndex(f => f.index == ind);
|
|
@@ -276,9 +252,10 @@
|
|
|
276
252
|
else {
|
|
277
253
|
spec.sort.push({ index: ind, dir: dir ? dir : null });
|
|
278
254
|
}
|
|
279
|
-
|
|
255
|
+
loadPage(spec.page.current);
|
|
280
256
|
}
|
|
281
|
-
function
|
|
257
|
+
// Internal load function (alias for adapter call)
|
|
258
|
+
function loadPage(currentPage) {
|
|
282
259
|
let dat = null;
|
|
283
260
|
if (props.data) {
|
|
284
261
|
if (Array.isArray(props.data))
|
|
@@ -288,8 +265,9 @@
|
|
|
288
265
|
return;
|
|
289
266
|
spec.status = TablevuStatus.Loading;
|
|
290
267
|
if (adapter) {
|
|
268
|
+
const pageSize = spec.page.size || 20;
|
|
291
269
|
adapter({
|
|
292
|
-
pageSize
|
|
270
|
+
pageSize,
|
|
293
271
|
currPage: currentPage,
|
|
294
272
|
sort: spec.sort,
|
|
295
273
|
cols: spec.columns,
|
|
@@ -303,7 +281,7 @@
|
|
|
303
281
|
const groupValue = spec.group.value;
|
|
304
282
|
if (groupValue && (typeof groupValue == 'string' || typeof groupValue == 'number' || typeof groupValue == 'bigint' || (typeof groupValue == 'object' && groupValue.value)))
|
|
305
283
|
prepareGroup(spec.group, rows);
|
|
306
|
-
spec.page.count = (ada.count > 0 &&
|
|
284
|
+
spec.page.count = (ada.count > 0 && pageSize > 0) ? Math.ceil(ada.count / pageSize) : 0;
|
|
307
285
|
spec.page.current = currentPage;
|
|
308
286
|
spec.status = TablevuStatus.Ready;
|
|
309
287
|
spec.time = Date.now();
|
|
@@ -365,8 +343,8 @@
|
|
|
365
343
|
o.style['text-align'] = col.align;
|
|
366
344
|
if (col.width)
|
|
367
345
|
o.style['max-width'] = col.width;
|
|
368
|
-
const f = col.render(row);
|
|
369
|
-
return vue.h('td', o, f);
|
|
346
|
+
const f = col.render?.(row) ?? '';
|
|
347
|
+
return vue.h('td', { ...o, innerHTML: f });
|
|
370
348
|
}
|
|
371
349
|
function renderGroup(grp) {
|
|
372
350
|
const b = vue.h('button', {
|
|
@@ -425,6 +403,10 @@
|
|
|
425
403
|
}
|
|
426
404
|
};
|
|
427
405
|
}
|
|
406
|
+
// Selection
|
|
407
|
+
if (spec.selectedRows.some(s => s[props.rowid || 'id'] === row[props.rowid || 'id'])) {
|
|
408
|
+
o.class = (o.class || '') + ' selected';
|
|
409
|
+
}
|
|
428
410
|
return vue.h('tr', o, r);
|
|
429
411
|
}
|
|
430
412
|
function renderHeader() {
|
|
@@ -475,7 +457,10 @@
|
|
|
475
457
|
else
|
|
476
458
|
a = vue.h('a', { href: '#', onClick: (event) => { orderby(i); event.preventDefault(); }, style: cy }, cl);
|
|
477
459
|
if (spec.columns[i].filter) ;
|
|
478
|
-
ar.push(vue.h('th', {
|
|
460
|
+
ar.push(vue.h('th', {
|
|
461
|
+
colspan: null,
|
|
462
|
+
style: ch
|
|
463
|
+
}, [a, f]));
|
|
479
464
|
}
|
|
480
465
|
const tr = vue.h('tr', {}, ar);
|
|
481
466
|
return [tr];
|
|
@@ -503,14 +488,34 @@
|
|
|
503
488
|
}
|
|
504
489
|
}
|
|
505
490
|
}
|
|
491
|
+
else if (spec.settings?.emptyMessage) {
|
|
492
|
+
dr.push(vue.h('tr', {}, vue.h('td', { colspan: spec.columns.length, style: { textAlign: 'center', padding: '2rem', color: '#666' } }, spec.settings.emptyMessage)));
|
|
493
|
+
}
|
|
506
494
|
return dr;
|
|
507
495
|
}
|
|
496
|
+
// Prompt user for page number and navigate
|
|
497
|
+
function goToPage() {
|
|
498
|
+
const input = prompt('Page number:', String(spec.page.current));
|
|
499
|
+
if (input) {
|
|
500
|
+
const pageNum = parseInt(input, 10);
|
|
501
|
+
if (!isNaN(pageNum) && pageNum > 0 && pageNum !== spec.page.current) {
|
|
502
|
+
page(pageNum);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
function makeHandler(fn) {
|
|
507
|
+
return (e) => {
|
|
508
|
+
e.preventDefault();
|
|
509
|
+
e.stopPropagation();
|
|
510
|
+
fn();
|
|
511
|
+
};
|
|
512
|
+
}
|
|
508
513
|
function renderFooter() {
|
|
509
|
-
const fr = vue.h('button', { class: spec.footer.button.class, style: 'font: initial; margin-right: .5rem', onClick: first, disabled: spec.page.current == 1 }, '◀◀');
|
|
510
|
-
const ls = vue.h('button', { class: spec.footer.button.class, style: 'font: initial; margin-right: .5rem', onClick: last, disabled: spec.page.count == 0 || spec.page.current == spec.page.count }, '▶▶');
|
|
511
|
-
const pg = vue.h('button', { class: spec.footer.button.class, style: 'font: initial; margin-right: .5rem', onClick:
|
|
512
|
-
const pr = vue.h('button', { class: spec.footer.button.class, style: 'font: initial; margin-right: .5rem', onClick: prior, disabled: spec.page.current == 1 }, '◀');
|
|
513
|
-
const nx = vue.h('button', { class: spec.footer.button.class, style: 'font: initial; margin-right: .5rem', onClick: next, disabled: spec.page.count > 0 && spec.page.current == spec.page.count }, '▶');
|
|
514
|
+
const fr = vue.h('button', { class: spec.footer.button.class, style: 'font: initial; margin-right: .5rem', onClick: makeHandler(first), disabled: spec.page.current == 1 }, '◀◀');
|
|
515
|
+
const ls = vue.h('button', { class: spec.footer.button.class, style: 'font: initial; margin-right: .5rem', onClick: makeHandler(last), disabled: spec.page.count == 0 || spec.page.current == spec.page.count }, '▶▶');
|
|
516
|
+
const pg = vue.h('button', { class: spec.footer.button.class, style: 'font: initial; margin-right: .5rem', onClick: makeHandler(goToPage) }, spec.page.current + (spec.page.count > 0 ? (' / ' + spec.page.count) : ''));
|
|
517
|
+
const pr = vue.h('button', { class: spec.footer.button.class, style: 'font: initial; margin-right: .5rem', onClick: makeHandler(prior), disabled: spec.page.current == 1 }, '◀');
|
|
518
|
+
const nx = vue.h('button', { class: spec.footer.button.class, style: 'font: initial; margin-right: .5rem', onClick: makeHandler(next), disabled: spec.page.count > 0 && spec.page.current == spec.page.count }, '▶');
|
|
514
519
|
const td = vue.h('td', { colspan: spec.columns.length, align: 'center' }, [fr, pr, pg, nx, ls]);
|
|
515
520
|
const tr = vue.h('tr', {}, [td]);
|
|
516
521
|
return [tr];
|
|
@@ -518,19 +523,41 @@
|
|
|
518
523
|
function renderCaption() {
|
|
519
524
|
return null;
|
|
520
525
|
}
|
|
526
|
+
// Initialize column metadata
|
|
521
527
|
if (spec.columns.length == 0) {
|
|
522
528
|
console.error('Columns not defined !');
|
|
523
529
|
}
|
|
524
|
-
for (let i = 0; i < spec.columns.length; i++)
|
|
530
|
+
for (let i = 0; i < spec.columns.length; i++) {
|
|
525
531
|
if (spec.columns[i].name && spec.columns[i].name.indexOf('.') > -1) {
|
|
526
532
|
spec.columns[i].depth = spec.columns[i].name.split('.');
|
|
527
533
|
}
|
|
528
|
-
|
|
534
|
+
// Initialize visibility
|
|
535
|
+
if (spec.columns[i].visible === undefined) {
|
|
536
|
+
spec.columns[i].visible = true;
|
|
537
|
+
spec.columnVisibility[spec.columns[i].name] = true;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
loadPage(1);
|
|
541
|
+
// Expose methods for external access via ref
|
|
542
|
+
expose({
|
|
543
|
+
first,
|
|
544
|
+
prior,
|
|
545
|
+
next,
|
|
546
|
+
last,
|
|
547
|
+
page,
|
|
548
|
+
refresh,
|
|
549
|
+
orderby,
|
|
550
|
+
getSelectedRows: () => spec.selectedRows,
|
|
551
|
+
setSelectedRows: (rows) => { spec.selectedRows = rows; }
|
|
552
|
+
});
|
|
529
553
|
vue.onMounted(() => {
|
|
530
554
|
// mounted hook
|
|
531
555
|
});
|
|
532
556
|
return {
|
|
533
|
-
spec, renderHeader, renderBody, renderFooter, renderCaption
|
|
557
|
+
spec, renderHeader, renderBody, renderFooter, renderCaption,
|
|
558
|
+
first, prior, next, last, page, refresh, orderby,
|
|
559
|
+
getSelectedRows: () => spec.selectedRows,
|
|
560
|
+
setSelectedRows: (rows) => { spec.selectedRows = rows; }
|
|
534
561
|
};
|
|
535
562
|
},
|
|
536
563
|
render(props) {
|
|
@@ -1077,7 +1104,6 @@
|
|
|
1077
1104
|
};
|
|
1078
1105
|
|
|
1079
1106
|
exports.TableVu = tablevu;
|
|
1080
|
-
exports.TablevuStatus = TablevuStatus;
|
|
1081
1107
|
exports.adaptArray = adaptArray;
|
|
1082
1108
|
exports.buildFilter = toODataFilter;
|
|
1083
1109
|
exports.odata = odata;
|
|
@@ -81,6 +81,7 @@ const TablevuStatus = {
|
|
|
81
81
|
Ready: 0,
|
|
82
82
|
Loading: 1
|
|
83
83
|
};
|
|
84
|
+
|
|
84
85
|
const tablevu = {
|
|
85
86
|
props: {
|
|
86
87
|
settings: { type: Object, default: null },
|
|
@@ -88,14 +89,13 @@ const tablevu = {
|
|
|
88
89
|
group: { type: [String, Object] },
|
|
89
90
|
search: { type: String },
|
|
90
91
|
filter: { type: [Array, Object] },
|
|
91
|
-
command: { type: Array, default: () => [] },
|
|
92
92
|
rowid: { type: String },
|
|
93
93
|
onRowClick: { type: Function },
|
|
94
94
|
onRowDblClick: { type: Function },
|
|
95
95
|
class: { type: String, default: 'table' },
|
|
96
96
|
style: { type: String, default: null }
|
|
97
97
|
},
|
|
98
|
-
emits: ['onRowClick', 'onRowDblClick'],
|
|
98
|
+
emits: ['onRowClick', 'onRowDblClick', 'selectionChange', 'columnVisibilityChange'],
|
|
99
99
|
setup(props, { attrs, slots, emit, expose }) {
|
|
100
100
|
let rows = [];
|
|
101
101
|
let rowg = [];
|
|
@@ -105,16 +105,16 @@ const tablevu = {
|
|
|
105
105
|
const spec = reactive({
|
|
106
106
|
caption: null,
|
|
107
107
|
group: {
|
|
108
|
-
value: (props.settings && props.settings.group) ? props.settings.group.value : props.group ? props.group :
|
|
109
|
-
content: (props.settings && props.settings.group) ? props.settings.group.content :
|
|
108
|
+
value: (props.settings && props.settings.group) ? props.settings.group.value : props.group ? props.group : undefined,
|
|
109
|
+
content: (props.settings && props.settings.group) ? props.settings.group.content : undefined,
|
|
110
110
|
expandAll: true,
|
|
111
111
|
class: 'table-light'
|
|
112
112
|
},
|
|
113
113
|
page: {
|
|
114
114
|
count: 0,
|
|
115
|
-
size: (props.settings && props.settings.page) ? props.settings.page.size : 0,
|
|
115
|
+
size: (props.settings && props.settings.page) ? (props.settings.page.size || 0) : 0,
|
|
116
116
|
current: 0,
|
|
117
|
-
type:
|
|
117
|
+
type: undefined
|
|
118
118
|
},
|
|
119
119
|
sort: (props.settings && props.settings.sort) ? props.settings.sort : [],
|
|
120
120
|
columns: (props.settings && props.settings.columns) ? props.settings.columns : [],
|
|
@@ -127,7 +127,11 @@ const tablevu = {
|
|
|
127
127
|
time: null,
|
|
128
128
|
search: null,
|
|
129
129
|
filter: null,
|
|
130
|
-
onData: (props.settings && props.settings.onData) ? props.settings.onData : undefined
|
|
130
|
+
onData: (props.settings && props.settings.onData) ? props.settings.onData : undefined,
|
|
131
|
+
selectedRows: [],
|
|
132
|
+
columnWidths: {},
|
|
133
|
+
columnOrder: [],
|
|
134
|
+
columnVisibility: {}
|
|
131
135
|
});
|
|
132
136
|
if (props.data) {
|
|
133
137
|
if (Array.isArray(props.data)) {
|
|
@@ -163,32 +167,6 @@ const tablevu = {
|
|
|
163
167
|
spec.filter = null;
|
|
164
168
|
refresh();
|
|
165
169
|
}, { deep: true });
|
|
166
|
-
watch(() => props.command, (n, o) => {
|
|
167
|
-
if (n && n.length > 0) {
|
|
168
|
-
const c = props.command[n.length - 1];
|
|
169
|
-
if (c && c.name) {
|
|
170
|
-
switch (c.name.toLowerCase()) {
|
|
171
|
-
case 'refresh':
|
|
172
|
-
refresh();
|
|
173
|
-
break;
|
|
174
|
-
case 'first':
|
|
175
|
-
first();
|
|
176
|
-
break;
|
|
177
|
-
case 'prior':
|
|
178
|
-
prior();
|
|
179
|
-
break;
|
|
180
|
-
case 'next':
|
|
181
|
-
next();
|
|
182
|
-
break;
|
|
183
|
-
case 'last':
|
|
184
|
-
last();
|
|
185
|
-
break;
|
|
186
|
-
default: console.log('Unknown command');
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
props.command.length = 0;
|
|
190
|
-
}
|
|
191
|
-
}, { deep: true });
|
|
192
170
|
function prepareGroup(g, r) {
|
|
193
171
|
grps = [];
|
|
194
172
|
rowg = [];
|
|
@@ -227,28 +205,26 @@ const tablevu = {
|
|
|
227
205
|
rowg.push(n);
|
|
228
206
|
}
|
|
229
207
|
}
|
|
230
|
-
function first() {
|
|
208
|
+
function first() { loadPage(1); }
|
|
231
209
|
function prior() {
|
|
232
210
|
if (spec.page.current > 1) {
|
|
233
|
-
|
|
211
|
+
loadPage(spec.page.current - 1);
|
|
234
212
|
}
|
|
235
213
|
else {
|
|
236
|
-
|
|
214
|
+
loadPage(spec.page.current);
|
|
237
215
|
}
|
|
238
216
|
}
|
|
239
|
-
function next() {
|
|
240
|
-
function last() {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
if (g && g > 0 && g != spec.page.current)
|
|
249
|
-
page(g);
|
|
217
|
+
function next() { loadPage(spec.page.current + 1); }
|
|
218
|
+
function last() { loadPage(spec.page.count); }
|
|
219
|
+
// Navigate to specific page number
|
|
220
|
+
function page(currentPage) {
|
|
221
|
+
if (currentPage < 1)
|
|
222
|
+
currentPage = 1;
|
|
223
|
+
if (currentPage > spec.page.count && spec.page.count > 0)
|
|
224
|
+
currentPage = spec.page.count;
|
|
225
|
+
loadPage(currentPage);
|
|
250
226
|
}
|
|
251
|
-
function refresh() {
|
|
227
|
+
function refresh() { loadPage(spec.page.current); }
|
|
252
228
|
function orderby(ind, dir) {
|
|
253
229
|
if (spec.sort && spec.sort.length > 0) {
|
|
254
230
|
let l = spec.sort.findIndex(f => f.index == ind);
|
|
@@ -272,9 +248,10 @@ const tablevu = {
|
|
|
272
248
|
else {
|
|
273
249
|
spec.sort.push({ index: ind, dir: dir ? dir : null });
|
|
274
250
|
}
|
|
275
|
-
|
|
251
|
+
loadPage(spec.page.current);
|
|
276
252
|
}
|
|
277
|
-
function
|
|
253
|
+
// Internal load function (alias for adapter call)
|
|
254
|
+
function loadPage(currentPage) {
|
|
278
255
|
let dat = null;
|
|
279
256
|
if (props.data) {
|
|
280
257
|
if (Array.isArray(props.data))
|
|
@@ -284,8 +261,9 @@ const tablevu = {
|
|
|
284
261
|
return;
|
|
285
262
|
spec.status = TablevuStatus.Loading;
|
|
286
263
|
if (adapter) {
|
|
264
|
+
const pageSize = spec.page.size || 20;
|
|
287
265
|
adapter({
|
|
288
|
-
pageSize
|
|
266
|
+
pageSize,
|
|
289
267
|
currPage: currentPage,
|
|
290
268
|
sort: spec.sort,
|
|
291
269
|
cols: spec.columns,
|
|
@@ -299,7 +277,7 @@ const tablevu = {
|
|
|
299
277
|
const groupValue = spec.group.value;
|
|
300
278
|
if (groupValue && (typeof groupValue == 'string' || typeof groupValue == 'number' || typeof groupValue == 'bigint' || (typeof groupValue == 'object' && groupValue.value)))
|
|
301
279
|
prepareGroup(spec.group, rows);
|
|
302
|
-
spec.page.count = (ada.count > 0 &&
|
|
280
|
+
spec.page.count = (ada.count > 0 && pageSize > 0) ? Math.ceil(ada.count / pageSize) : 0;
|
|
303
281
|
spec.page.current = currentPage;
|
|
304
282
|
spec.status = TablevuStatus.Ready;
|
|
305
283
|
spec.time = Date.now();
|
|
@@ -361,8 +339,8 @@ const tablevu = {
|
|
|
361
339
|
o.style['text-align'] = col.align;
|
|
362
340
|
if (col.width)
|
|
363
341
|
o.style['max-width'] = col.width;
|
|
364
|
-
const f = col.render(row);
|
|
365
|
-
return h('td', o, f);
|
|
342
|
+
const f = col.render?.(row) ?? '';
|
|
343
|
+
return h('td', { ...o, innerHTML: f });
|
|
366
344
|
}
|
|
367
345
|
function renderGroup(grp) {
|
|
368
346
|
const b = h('button', {
|
|
@@ -421,6 +399,10 @@ const tablevu = {
|
|
|
421
399
|
}
|
|
422
400
|
};
|
|
423
401
|
}
|
|
402
|
+
// Selection
|
|
403
|
+
if (spec.selectedRows.some(s => s[props.rowid || 'id'] === row[props.rowid || 'id'])) {
|
|
404
|
+
o.class = (o.class || '') + ' selected';
|
|
405
|
+
}
|
|
424
406
|
return h('tr', o, r);
|
|
425
407
|
}
|
|
426
408
|
function renderHeader() {
|
|
@@ -471,7 +453,10 @@ const tablevu = {
|
|
|
471
453
|
else
|
|
472
454
|
a = h('a', { href: '#', onClick: (event) => { orderby(i); event.preventDefault(); }, style: cy }, cl);
|
|
473
455
|
if (spec.columns[i].filter) ;
|
|
474
|
-
ar.push(h('th', {
|
|
456
|
+
ar.push(h('th', {
|
|
457
|
+
colspan: null,
|
|
458
|
+
style: ch
|
|
459
|
+
}, [a, f]));
|
|
475
460
|
}
|
|
476
461
|
const tr = h('tr', {}, ar);
|
|
477
462
|
return [tr];
|
|
@@ -499,14 +484,34 @@ const tablevu = {
|
|
|
499
484
|
}
|
|
500
485
|
}
|
|
501
486
|
}
|
|
487
|
+
else if (spec.settings?.emptyMessage) {
|
|
488
|
+
dr.push(h('tr', {}, h('td', { colspan: spec.columns.length, style: { textAlign: 'center', padding: '2rem', color: '#666' } }, spec.settings.emptyMessage)));
|
|
489
|
+
}
|
|
502
490
|
return dr;
|
|
503
491
|
}
|
|
492
|
+
// Prompt user for page number and navigate
|
|
493
|
+
function goToPage() {
|
|
494
|
+
const input = prompt('Page number:', String(spec.page.current));
|
|
495
|
+
if (input) {
|
|
496
|
+
const pageNum = parseInt(input, 10);
|
|
497
|
+
if (!isNaN(pageNum) && pageNum > 0 && pageNum !== spec.page.current) {
|
|
498
|
+
page(pageNum);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
function makeHandler(fn) {
|
|
503
|
+
return (e) => {
|
|
504
|
+
e.preventDefault();
|
|
505
|
+
e.stopPropagation();
|
|
506
|
+
fn();
|
|
507
|
+
};
|
|
508
|
+
}
|
|
504
509
|
function renderFooter() {
|
|
505
|
-
const fr = h('button', { class: spec.footer.button.class, style: 'font: initial; margin-right: .5rem', onClick: first, disabled: spec.page.current == 1 }, '◀◀');
|
|
506
|
-
const ls = h('button', { class: spec.footer.button.class, style: 'font: initial; margin-right: .5rem', onClick: last, disabled: spec.page.count == 0 || spec.page.current == spec.page.count }, '▶▶');
|
|
507
|
-
const pg = h('button', { class: spec.footer.button.class, style: 'font: initial; margin-right: .5rem', onClick:
|
|
508
|
-
const pr = h('button', { class: spec.footer.button.class, style: 'font: initial; margin-right: .5rem', onClick: prior, disabled: spec.page.current == 1 }, '◀');
|
|
509
|
-
const nx = h('button', { class: spec.footer.button.class, style: 'font: initial; margin-right: .5rem', onClick: next, disabled: spec.page.count > 0 && spec.page.current == spec.page.count }, '▶');
|
|
510
|
+
const fr = h('button', { class: spec.footer.button.class, style: 'font: initial; margin-right: .5rem', onClick: makeHandler(first), disabled: spec.page.current == 1 }, '◀◀');
|
|
511
|
+
const ls = h('button', { class: spec.footer.button.class, style: 'font: initial; margin-right: .5rem', onClick: makeHandler(last), disabled: spec.page.count == 0 || spec.page.current == spec.page.count }, '▶▶');
|
|
512
|
+
const pg = h('button', { class: spec.footer.button.class, style: 'font: initial; margin-right: .5rem', onClick: makeHandler(goToPage) }, spec.page.current + (spec.page.count > 0 ? (' / ' + spec.page.count) : ''));
|
|
513
|
+
const pr = h('button', { class: spec.footer.button.class, style: 'font: initial; margin-right: .5rem', onClick: makeHandler(prior), disabled: spec.page.current == 1 }, '◀');
|
|
514
|
+
const nx = h('button', { class: spec.footer.button.class, style: 'font: initial; margin-right: .5rem', onClick: makeHandler(next), disabled: spec.page.count > 0 && spec.page.current == spec.page.count }, '▶');
|
|
510
515
|
const td = h('td', { colspan: spec.columns.length, align: 'center' }, [fr, pr, pg, nx, ls]);
|
|
511
516
|
const tr = h('tr', {}, [td]);
|
|
512
517
|
return [tr];
|
|
@@ -514,19 +519,41 @@ const tablevu = {
|
|
|
514
519
|
function renderCaption() {
|
|
515
520
|
return null;
|
|
516
521
|
}
|
|
522
|
+
// Initialize column metadata
|
|
517
523
|
if (spec.columns.length == 0) {
|
|
518
524
|
console.error('Columns not defined !');
|
|
519
525
|
}
|
|
520
|
-
for (let i = 0; i < spec.columns.length; i++)
|
|
526
|
+
for (let i = 0; i < spec.columns.length; i++) {
|
|
521
527
|
if (spec.columns[i].name && spec.columns[i].name.indexOf('.') > -1) {
|
|
522
528
|
spec.columns[i].depth = spec.columns[i].name.split('.');
|
|
523
529
|
}
|
|
524
|
-
|
|
530
|
+
// Initialize visibility
|
|
531
|
+
if (spec.columns[i].visible === undefined) {
|
|
532
|
+
spec.columns[i].visible = true;
|
|
533
|
+
spec.columnVisibility[spec.columns[i].name] = true;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
loadPage(1);
|
|
537
|
+
// Expose methods for external access via ref
|
|
538
|
+
expose({
|
|
539
|
+
first,
|
|
540
|
+
prior,
|
|
541
|
+
next,
|
|
542
|
+
last,
|
|
543
|
+
page,
|
|
544
|
+
refresh,
|
|
545
|
+
orderby,
|
|
546
|
+
getSelectedRows: () => spec.selectedRows,
|
|
547
|
+
setSelectedRows: (rows) => { spec.selectedRows = rows; }
|
|
548
|
+
});
|
|
525
549
|
onMounted(() => {
|
|
526
550
|
// mounted hook
|
|
527
551
|
});
|
|
528
552
|
return {
|
|
529
|
-
spec, renderHeader, renderBody, renderFooter, renderCaption
|
|
553
|
+
spec, renderHeader, renderBody, renderFooter, renderCaption,
|
|
554
|
+
first, prior, next, last, page, refresh, orderby,
|
|
555
|
+
getSelectedRows: () => spec.selectedRows,
|
|
556
|
+
setSelectedRows: (rows) => { spec.selectedRows = rows; }
|
|
530
557
|
};
|
|
531
558
|
},
|
|
532
559
|
render(props) {
|
|
@@ -548,4 +575,4 @@ const tablevu = {
|
|
|
548
575
|
}
|
|
549
576
|
};
|
|
550
577
|
|
|
551
|
-
export {
|
|
578
|
+
export { tablevu as default };
|