tablevu 0.3.0-beta.5 → 0.3.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/dist/tablevu.cjs +109 -7
- package/dist/tablevu.esm.js +109 -7
- package/package.json +1 -1
package/dist/tablevu.cjs
CHANGED
|
@@ -107,6 +107,8 @@ const tablevu = vue.defineComponent({
|
|
|
107
107
|
let groups = [];
|
|
108
108
|
let adapter = null;
|
|
109
109
|
let searchTimer = null;
|
|
110
|
+
let draggedColumnName = null;
|
|
111
|
+
let resizeCleanup = null;
|
|
110
112
|
const state = vue.reactive({
|
|
111
113
|
caption: null,
|
|
112
114
|
group: {
|
|
@@ -121,8 +123,12 @@ const tablevu = vue.defineComponent({
|
|
|
121
123
|
current: 0,
|
|
122
124
|
type: null
|
|
123
125
|
},
|
|
124
|
-
sort: (props.settings
|
|
125
|
-
columns: (props.settings
|
|
126
|
+
sort: (props.settings?.sort ?? []).map(sort => ({ ...sort })),
|
|
127
|
+
columns: (props.settings?.columns ?? []).map(column => ({
|
|
128
|
+
...column,
|
|
129
|
+
style: column.style ? { ...column.style } : undefined,
|
|
130
|
+
depth: column.depth ? [...column.depth] : undefined
|
|
131
|
+
})),
|
|
126
132
|
footer: {
|
|
127
133
|
button: {
|
|
128
134
|
class: (props.settings && props.settings.footer && props.settings.footer.button && props.settings.footer.button.class) || 'btn'
|
|
@@ -163,7 +169,62 @@ const tablevu = vue.defineComponent({
|
|
|
163
169
|
vue.onBeforeUnmount(() => {
|
|
164
170
|
if (searchTimer)
|
|
165
171
|
clearTimeout(searchTimer);
|
|
172
|
+
resizeCleanup?.();
|
|
166
173
|
});
|
|
174
|
+
function remapSortColumns(previousNames) {
|
|
175
|
+
state.sort.forEach((sort, index) => {
|
|
176
|
+
const name = previousNames[index] ?? sort.name;
|
|
177
|
+
if (!name)
|
|
178
|
+
return;
|
|
179
|
+
const columnIndex = state.columns.findIndex(column => column.name === name);
|
|
180
|
+
if (columnIndex >= 0)
|
|
181
|
+
sort.index = columnIndex;
|
|
182
|
+
else {
|
|
183
|
+
sort.name = name;
|
|
184
|
+
delete sort.index;
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
function reorderColumn(sourceName, targetName) {
|
|
189
|
+
const sourceIndex = state.columns.findIndex(column => column.name === sourceName);
|
|
190
|
+
const targetIndex = state.columns.findIndex(column => column.name === targetName);
|
|
191
|
+
if (sourceIndex < 0 || targetIndex < 0 || sourceIndex === targetIndex)
|
|
192
|
+
return;
|
|
193
|
+
const sortNames = state.sort.map(sort => sort.index !== undefined
|
|
194
|
+
? state.columns[sort.index]?.name
|
|
195
|
+
: sort.name);
|
|
196
|
+
const [column] = state.columns.splice(sourceIndex, 1);
|
|
197
|
+
state.columns.splice(targetIndex, 0, column);
|
|
198
|
+
remapSortColumns(sortNames);
|
|
199
|
+
}
|
|
200
|
+
function hideColumn(name) {
|
|
201
|
+
const sortNames = state.sort.map(sort => sort.index !== undefined
|
|
202
|
+
? state.columns[sort.index]?.name
|
|
203
|
+
: sort.name);
|
|
204
|
+
const index = state.columns.findIndex(column => column.name === name);
|
|
205
|
+
if (index < 0)
|
|
206
|
+
return;
|
|
207
|
+
state.columns.splice(index, 1);
|
|
208
|
+
remapSortColumns(sortNames);
|
|
209
|
+
}
|
|
210
|
+
function startColumnResize(event, column, header) {
|
|
211
|
+
event.preventDefault();
|
|
212
|
+
event.stopPropagation();
|
|
213
|
+
resizeCleanup?.();
|
|
214
|
+
const startX = event.clientX;
|
|
215
|
+
const startWidth = header.getBoundingClientRect().width;
|
|
216
|
+
const move = (moveEvent) => {
|
|
217
|
+
column.width = `${Math.max(40, startWidth + moveEvent.clientX - startX)}px`;
|
|
218
|
+
};
|
|
219
|
+
const up = () => {
|
|
220
|
+
document.removeEventListener('pointermove', move);
|
|
221
|
+
document.removeEventListener('pointerup', up);
|
|
222
|
+
resizeCleanup = null;
|
|
223
|
+
};
|
|
224
|
+
resizeCleanup = up;
|
|
225
|
+
document.addEventListener('pointermove', move);
|
|
226
|
+
document.addEventListener('pointerup', up);
|
|
227
|
+
}
|
|
167
228
|
if (props.filter)
|
|
168
229
|
state.filter = props.filter;
|
|
169
230
|
vue.watch(() => props.filter, () => {
|
|
@@ -456,11 +517,12 @@ const tablevu = vue.defineComponent({
|
|
|
456
517
|
else
|
|
457
518
|
labelContent.push(vue.h('span', { style: { float: 'right' } }, '▲'));
|
|
458
519
|
}
|
|
520
|
+
const column = state.columns[i];
|
|
459
521
|
const headerStyle = { position: 'relative' };
|
|
460
|
-
if (
|
|
461
|
-
headerStyle.width =
|
|
462
|
-
headerStyle.minWidth =
|
|
463
|
-
headerStyle.maxWidth =
|
|
522
|
+
if (column.width) {
|
|
523
|
+
headerStyle.width = column.width;
|
|
524
|
+
headerStyle.minWidth = column.width;
|
|
525
|
+
headerStyle.maxWidth = column.width;
|
|
464
526
|
}
|
|
465
527
|
let headerLink;
|
|
466
528
|
let popupContent;
|
|
@@ -489,7 +551,47 @@ const tablevu = vue.defineComponent({
|
|
|
489
551
|
else
|
|
490
552
|
headerLink = vue.h('a', { href: '#', onClick: (event) => { sortBy(i); event.preventDefault(); }, style: { display: 'block', 'font-weight': 500, textDecoration: 'none', textAlign: 'center' } }, labelContent);
|
|
491
553
|
if (state.columns[i].filter) ;
|
|
492
|
-
|
|
554
|
+
const resizeHandle = column.resizable === false ? null : vue.h('div', {
|
|
555
|
+
'aria-hidden': 'true',
|
|
556
|
+
'onPointerdown': (event) => startColumnResize(event, column, event.currentTarget.parentElement),
|
|
557
|
+
style: { position: 'absolute', top: 0, right: '-3px', width: '6px', height: '100%', cursor: 'col-resize', touchAction: 'none', zIndex: 2 }
|
|
558
|
+
});
|
|
559
|
+
headers.push(vue.h('th', {
|
|
560
|
+
colspan: null,
|
|
561
|
+
style: headerStyle,
|
|
562
|
+
draggable: column.draggable !== false,
|
|
563
|
+
onDragstart: (event) => {
|
|
564
|
+
if (event.target.closest('[aria-hidden="true"]')) {
|
|
565
|
+
event.preventDefault();
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
draggedColumnName = column.name;
|
|
569
|
+
if (event.dataTransfer) {
|
|
570
|
+
event.dataTransfer.effectAllowed = 'move';
|
|
571
|
+
event.dataTransfer.setData('text/plain', column.name);
|
|
572
|
+
}
|
|
573
|
+
},
|
|
574
|
+
onDragover: (event) => {
|
|
575
|
+
if (draggedColumnName) {
|
|
576
|
+
event.preventDefault();
|
|
577
|
+
if (event.dataTransfer)
|
|
578
|
+
event.dataTransfer.dropEffect = 'move';
|
|
579
|
+
}
|
|
580
|
+
},
|
|
581
|
+
onDrop: (event) => {
|
|
582
|
+
if (!draggedColumnName)
|
|
583
|
+
return;
|
|
584
|
+
event.preventDefault();
|
|
585
|
+
reorderColumn(draggedColumnName, column.name);
|
|
586
|
+
},
|
|
587
|
+
onDragend: (event) => {
|
|
588
|
+
const name = draggedColumnName;
|
|
589
|
+
draggedColumnName = null;
|
|
590
|
+
const rect = event.currentTarget.closest('table')?.getBoundingClientRect();
|
|
591
|
+
if (name && rect && (event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom))
|
|
592
|
+
hideColumn(name);
|
|
593
|
+
}
|
|
594
|
+
}, [headerLink, popupContent, resizeHandle]));
|
|
493
595
|
}
|
|
494
596
|
return [vue.h('tr', {}, headers)];
|
|
495
597
|
}
|
package/dist/tablevu.esm.js
CHANGED
|
@@ -105,6 +105,8 @@ const tablevu = defineComponent({
|
|
|
105
105
|
let groups = [];
|
|
106
106
|
let adapter = null;
|
|
107
107
|
let searchTimer = null;
|
|
108
|
+
let draggedColumnName = null;
|
|
109
|
+
let resizeCleanup = null;
|
|
108
110
|
const state = reactive({
|
|
109
111
|
caption: null,
|
|
110
112
|
group: {
|
|
@@ -119,8 +121,12 @@ const tablevu = defineComponent({
|
|
|
119
121
|
current: 0,
|
|
120
122
|
type: null
|
|
121
123
|
},
|
|
122
|
-
sort: (props.settings
|
|
123
|
-
columns: (props.settings
|
|
124
|
+
sort: (props.settings?.sort ?? []).map(sort => ({ ...sort })),
|
|
125
|
+
columns: (props.settings?.columns ?? []).map(column => ({
|
|
126
|
+
...column,
|
|
127
|
+
style: column.style ? { ...column.style } : undefined,
|
|
128
|
+
depth: column.depth ? [...column.depth] : undefined
|
|
129
|
+
})),
|
|
124
130
|
footer: {
|
|
125
131
|
button: {
|
|
126
132
|
class: (props.settings && props.settings.footer && props.settings.footer.button && props.settings.footer.button.class) || 'btn'
|
|
@@ -161,7 +167,62 @@ const tablevu = defineComponent({
|
|
|
161
167
|
onBeforeUnmount(() => {
|
|
162
168
|
if (searchTimer)
|
|
163
169
|
clearTimeout(searchTimer);
|
|
170
|
+
resizeCleanup?.();
|
|
164
171
|
});
|
|
172
|
+
function remapSortColumns(previousNames) {
|
|
173
|
+
state.sort.forEach((sort, index) => {
|
|
174
|
+
const name = previousNames[index] ?? sort.name;
|
|
175
|
+
if (!name)
|
|
176
|
+
return;
|
|
177
|
+
const columnIndex = state.columns.findIndex(column => column.name === name);
|
|
178
|
+
if (columnIndex >= 0)
|
|
179
|
+
sort.index = columnIndex;
|
|
180
|
+
else {
|
|
181
|
+
sort.name = name;
|
|
182
|
+
delete sort.index;
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
function reorderColumn(sourceName, targetName) {
|
|
187
|
+
const sourceIndex = state.columns.findIndex(column => column.name === sourceName);
|
|
188
|
+
const targetIndex = state.columns.findIndex(column => column.name === targetName);
|
|
189
|
+
if (sourceIndex < 0 || targetIndex < 0 || sourceIndex === targetIndex)
|
|
190
|
+
return;
|
|
191
|
+
const sortNames = state.sort.map(sort => sort.index !== undefined
|
|
192
|
+
? state.columns[sort.index]?.name
|
|
193
|
+
: sort.name);
|
|
194
|
+
const [column] = state.columns.splice(sourceIndex, 1);
|
|
195
|
+
state.columns.splice(targetIndex, 0, column);
|
|
196
|
+
remapSortColumns(sortNames);
|
|
197
|
+
}
|
|
198
|
+
function hideColumn(name) {
|
|
199
|
+
const sortNames = state.sort.map(sort => sort.index !== undefined
|
|
200
|
+
? state.columns[sort.index]?.name
|
|
201
|
+
: sort.name);
|
|
202
|
+
const index = state.columns.findIndex(column => column.name === name);
|
|
203
|
+
if (index < 0)
|
|
204
|
+
return;
|
|
205
|
+
state.columns.splice(index, 1);
|
|
206
|
+
remapSortColumns(sortNames);
|
|
207
|
+
}
|
|
208
|
+
function startColumnResize(event, column, header) {
|
|
209
|
+
event.preventDefault();
|
|
210
|
+
event.stopPropagation();
|
|
211
|
+
resizeCleanup?.();
|
|
212
|
+
const startX = event.clientX;
|
|
213
|
+
const startWidth = header.getBoundingClientRect().width;
|
|
214
|
+
const move = (moveEvent) => {
|
|
215
|
+
column.width = `${Math.max(40, startWidth + moveEvent.clientX - startX)}px`;
|
|
216
|
+
};
|
|
217
|
+
const up = () => {
|
|
218
|
+
document.removeEventListener('pointermove', move);
|
|
219
|
+
document.removeEventListener('pointerup', up);
|
|
220
|
+
resizeCleanup = null;
|
|
221
|
+
};
|
|
222
|
+
resizeCleanup = up;
|
|
223
|
+
document.addEventListener('pointermove', move);
|
|
224
|
+
document.addEventListener('pointerup', up);
|
|
225
|
+
}
|
|
165
226
|
if (props.filter)
|
|
166
227
|
state.filter = props.filter;
|
|
167
228
|
watch(() => props.filter, () => {
|
|
@@ -454,11 +515,12 @@ const tablevu = defineComponent({
|
|
|
454
515
|
else
|
|
455
516
|
labelContent.push(h('span', { style: { float: 'right' } }, '▲'));
|
|
456
517
|
}
|
|
518
|
+
const column = state.columns[i];
|
|
457
519
|
const headerStyle = { position: 'relative' };
|
|
458
|
-
if (
|
|
459
|
-
headerStyle.width =
|
|
460
|
-
headerStyle.minWidth =
|
|
461
|
-
headerStyle.maxWidth =
|
|
520
|
+
if (column.width) {
|
|
521
|
+
headerStyle.width = column.width;
|
|
522
|
+
headerStyle.minWidth = column.width;
|
|
523
|
+
headerStyle.maxWidth = column.width;
|
|
462
524
|
}
|
|
463
525
|
let headerLink;
|
|
464
526
|
let popupContent;
|
|
@@ -487,7 +549,47 @@ const tablevu = defineComponent({
|
|
|
487
549
|
else
|
|
488
550
|
headerLink = h('a', { href: '#', onClick: (event) => { sortBy(i); event.preventDefault(); }, style: { display: 'block', 'font-weight': 500, textDecoration: 'none', textAlign: 'center' } }, labelContent);
|
|
489
551
|
if (state.columns[i].filter) ;
|
|
490
|
-
|
|
552
|
+
const resizeHandle = column.resizable === false ? null : h('div', {
|
|
553
|
+
'aria-hidden': 'true',
|
|
554
|
+
'onPointerdown': (event) => startColumnResize(event, column, event.currentTarget.parentElement),
|
|
555
|
+
style: { position: 'absolute', top: 0, right: '-3px', width: '6px', height: '100%', cursor: 'col-resize', touchAction: 'none', zIndex: 2 }
|
|
556
|
+
});
|
|
557
|
+
headers.push(h('th', {
|
|
558
|
+
colspan: null,
|
|
559
|
+
style: headerStyle,
|
|
560
|
+
draggable: column.draggable !== false,
|
|
561
|
+
onDragstart: (event) => {
|
|
562
|
+
if (event.target.closest('[aria-hidden="true"]')) {
|
|
563
|
+
event.preventDefault();
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
draggedColumnName = column.name;
|
|
567
|
+
if (event.dataTransfer) {
|
|
568
|
+
event.dataTransfer.effectAllowed = 'move';
|
|
569
|
+
event.dataTransfer.setData('text/plain', column.name);
|
|
570
|
+
}
|
|
571
|
+
},
|
|
572
|
+
onDragover: (event) => {
|
|
573
|
+
if (draggedColumnName) {
|
|
574
|
+
event.preventDefault();
|
|
575
|
+
if (event.dataTransfer)
|
|
576
|
+
event.dataTransfer.dropEffect = 'move';
|
|
577
|
+
}
|
|
578
|
+
},
|
|
579
|
+
onDrop: (event) => {
|
|
580
|
+
if (!draggedColumnName)
|
|
581
|
+
return;
|
|
582
|
+
event.preventDefault();
|
|
583
|
+
reorderColumn(draggedColumnName, column.name);
|
|
584
|
+
},
|
|
585
|
+
onDragend: (event) => {
|
|
586
|
+
const name = draggedColumnName;
|
|
587
|
+
draggedColumnName = null;
|
|
588
|
+
const rect = event.currentTarget.closest('table')?.getBoundingClientRect();
|
|
589
|
+
if (name && rect && (event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom))
|
|
590
|
+
hideColumn(name);
|
|
591
|
+
}
|
|
592
|
+
}, [headerLink, popupContent, resizeHandle]));
|
|
491
593
|
}
|
|
492
594
|
return [h('tr', {}, headers)];
|
|
493
595
|
}
|