@vaadin/grid 22.0.0-alpha7
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/LICENSE +190 -0
- package/README.md +79 -0
- package/all-imports.js +1 -0
- package/package.json +58 -0
- package/src/all-imports.js +14 -0
- package/src/array-data-provider.js +145 -0
- package/src/interfaces.d.ts +75 -0
- package/src/vaadin-grid-a11y-mixin.js +158 -0
- package/src/vaadin-grid-active-item-mixin.d.ts +19 -0
- package/src/vaadin-grid-active-item-mixin.js +117 -0
- package/src/vaadin-grid-array-data-provider-mixin.d.ts +16 -0
- package/src/vaadin-grid-array-data-provider-mixin.js +75 -0
- package/src/vaadin-grid-column-group.d.ts +54 -0
- package/src/vaadin-grid-column-group.js +320 -0
- package/src/vaadin-grid-column-reordering-mixin.d.ts +19 -0
- package/src/vaadin-grid-column-reordering-mixin.js +387 -0
- package/src/vaadin-grid-column-resizing-mixin.js +111 -0
- package/src/vaadin-grid-column.d.ts +133 -0
- package/src/vaadin-grid-column.js +745 -0
- package/src/vaadin-grid-data-provider-mixin.d.ts +108 -0
- package/src/vaadin-grid-data-provider-mixin.js +520 -0
- package/src/vaadin-grid-drag-and-drop-mixin.d.ts +69 -0
- package/src/vaadin-grid-drag-and-drop-mixin.js +433 -0
- package/src/vaadin-grid-dynamic-columns-mixin.js +180 -0
- package/src/vaadin-grid-event-context-mixin.d.ts +33 -0
- package/src/vaadin-grid-event-context-mixin.js +57 -0
- package/src/vaadin-grid-filter-column.d.ts +35 -0
- package/src/vaadin-grid-filter-column.js +120 -0
- package/src/vaadin-grid-filter-mixin.js +76 -0
- package/src/vaadin-grid-filter.d.ts +67 -0
- package/src/vaadin-grid-filter.js +125 -0
- package/src/vaadin-grid-helpers.js +23 -0
- package/src/vaadin-grid-keyboard-navigation-mixin.js +891 -0
- package/src/vaadin-grid-row-details-mixin.d.ts +44 -0
- package/src/vaadin-grid-row-details-mixin.js +200 -0
- package/src/vaadin-grid-scroll-mixin.d.ts +18 -0
- package/src/vaadin-grid-scroll-mixin.js +202 -0
- package/src/vaadin-grid-selection-column.d.ts +71 -0
- package/src/vaadin-grid-selection-column.js +285 -0
- package/src/vaadin-grid-selection-mixin.d.ts +30 -0
- package/src/vaadin-grid-selection-mixin.js +93 -0
- package/src/vaadin-grid-sort-column.d.ts +63 -0
- package/src/vaadin-grid-sort-column.js +118 -0
- package/src/vaadin-grid-sort-mixin.d.ts +15 -0
- package/src/vaadin-grid-sort-mixin.js +139 -0
- package/src/vaadin-grid-sorter.d.ts +94 -0
- package/src/vaadin-grid-sorter.js +230 -0
- package/src/vaadin-grid-styles.js +297 -0
- package/src/vaadin-grid-styling-mixin.d.ts +37 -0
- package/src/vaadin-grid-styling-mixin.js +71 -0
- package/src/vaadin-grid-tree-column.d.ts +36 -0
- package/src/vaadin-grid-tree-column.js +119 -0
- package/src/vaadin-grid-tree-toggle.d.ts +104 -0
- package/src/vaadin-grid-tree-toggle.js +205 -0
- package/src/vaadin-grid.d.ts +397 -0
- package/src/vaadin-grid.js +1004 -0
- package/theme/lumo/all-imports.js +11 -0
- package/theme/lumo/vaadin-grid-column-group.js +1 -0
- package/theme/lumo/vaadin-grid-column.js +1 -0
- package/theme/lumo/vaadin-grid-filter-column.js +2 -0
- package/theme/lumo/vaadin-grid-filter.js +2 -0
- package/theme/lumo/vaadin-grid-selection-column.js +2 -0
- package/theme/lumo/vaadin-grid-sort-column.js +2 -0
- package/theme/lumo/vaadin-grid-sorter-styles.js +53 -0
- package/theme/lumo/vaadin-grid-sorter.js +2 -0
- package/theme/lumo/vaadin-grid-styles.js +378 -0
- package/theme/lumo/vaadin-grid-tree-column.js +2 -0
- package/theme/lumo/vaadin-grid-tree-toggle-styles.js +112 -0
- package/theme/lumo/vaadin-grid-tree-toggle.js +2 -0
- package/theme/lumo/vaadin-grid.js +9 -0
- package/theme/material/all-imports.js +11 -0
- package/theme/material/vaadin-grid-column-group.js +1 -0
- package/theme/material/vaadin-grid-column.js +1 -0
- package/theme/material/vaadin-grid-filter-column.js +2 -0
- package/theme/material/vaadin-grid-filter.js +2 -0
- package/theme/material/vaadin-grid-selection-column.js +2 -0
- package/theme/material/vaadin-grid-sort-column.js +2 -0
- package/theme/material/vaadin-grid-sorter-styles.js +72 -0
- package/theme/material/vaadin-grid-sorter.js +2 -0
- package/theme/material/vaadin-grid-styles.js +252 -0
- package/theme/material/vaadin-grid-tree-column.js +2 -0
- package/theme/material/vaadin-grid-tree-toggle-styles.js +42 -0
- package/theme/material/vaadin-grid-tree-toggle.js +2 -0
- package/theme/material/vaadin-grid.js +2 -0
- package/vaadin-grid-column-group.d.ts +1 -0
- package/vaadin-grid-column-group.js +3 -0
- package/vaadin-grid-column.d.ts +1 -0
- package/vaadin-grid-column.js +3 -0
- package/vaadin-grid-filter-column.d.ts +1 -0
- package/vaadin-grid-filter-column.js +3 -0
- package/vaadin-grid-filter.d.ts +1 -0
- package/vaadin-grid-filter.js +3 -0
- package/vaadin-grid-selection-column.d.ts +1 -0
- package/vaadin-grid-selection-column.js +3 -0
- package/vaadin-grid-sort-column.d.ts +1 -0
- package/vaadin-grid-sort-column.js +3 -0
- package/vaadin-grid-sorter.d.ts +1 -0
- package/vaadin-grid-sorter.js +3 -0
- package/vaadin-grid-tree-column.d.ts +1 -0
- package/vaadin-grid-tree-column.js +3 -0
- package/vaadin-grid-tree-toggle.d.ts +1 -0
- package/vaadin-grid-tree-toggle.js +3 -0
- package/vaadin-grid.d.ts +3 -0
- package/vaadin-grid.js +4 -0
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2021 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { GestureEventListeners } from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
|
|
7
|
+
import { addListener } from '@polymer/polymer/lib/utils/gestures.js';
|
|
8
|
+
import { updateColumnOrders } from './vaadin-grid-helpers.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @polymerMixin
|
|
12
|
+
*/
|
|
13
|
+
export const ColumnReorderingMixin = (superClass) =>
|
|
14
|
+
class ColumnReorderingMixin extends GestureEventListeners(superClass) {
|
|
15
|
+
static get properties() {
|
|
16
|
+
return {
|
|
17
|
+
/**
|
|
18
|
+
* Set to true to allow column reordering.
|
|
19
|
+
* @attr {boolean} column-reordering-allowed
|
|
20
|
+
* @type {boolean}
|
|
21
|
+
*/
|
|
22
|
+
columnReorderingAllowed: {
|
|
23
|
+
type: Boolean,
|
|
24
|
+
value: false
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
/** @private */
|
|
28
|
+
_orderBaseScope: {
|
|
29
|
+
type: Number,
|
|
30
|
+
value: 10000000
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static get observers() {
|
|
36
|
+
return ['_updateOrders(_columnTree, _columnTree.*)'];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
ready() {
|
|
40
|
+
super.ready();
|
|
41
|
+
addListener(this, 'track', this._onTrackEvent);
|
|
42
|
+
this._reorderGhost = this.shadowRoot.querySelector('[part="reorder-ghost"]');
|
|
43
|
+
|
|
44
|
+
this.addEventListener('touchstart', this._onTouchStart.bind(this));
|
|
45
|
+
this.addEventListener('touchmove', this._onTouchMove.bind(this));
|
|
46
|
+
this.addEventListener('touchend', this._onTouchEnd.bind(this));
|
|
47
|
+
this.addEventListener('contextmenu', this._onContextMenu.bind(this));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** @private */
|
|
51
|
+
_onContextMenu(e) {
|
|
52
|
+
if (this.hasAttribute('reordering')) {
|
|
53
|
+
e.preventDefault();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** @private */
|
|
58
|
+
_onTouchStart(e) {
|
|
59
|
+
// Touch event, delay activation by 100ms
|
|
60
|
+
this._startTouchReorderTimeout = setTimeout(() => {
|
|
61
|
+
this._onTrackStart({
|
|
62
|
+
detail: {
|
|
63
|
+
x: e.touches[0].clientX,
|
|
64
|
+
y: e.touches[0].clientY
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}, 100);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** @private */
|
|
71
|
+
_onTouchMove(e) {
|
|
72
|
+
if (this._draggedColumn) {
|
|
73
|
+
e.preventDefault();
|
|
74
|
+
}
|
|
75
|
+
clearTimeout(this._startTouchReorderTimeout);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** @private */
|
|
79
|
+
_onTouchEnd() {
|
|
80
|
+
clearTimeout(this._startTouchReorderTimeout);
|
|
81
|
+
this._onTrackEnd();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** @private */
|
|
85
|
+
_onTrackEvent(e) {
|
|
86
|
+
if (e.detail.state === 'start') {
|
|
87
|
+
const path = e.composedPath();
|
|
88
|
+
const headerCell = path[path.indexOf(this.$.header) - 2];
|
|
89
|
+
if (!headerCell || !headerCell._content) {
|
|
90
|
+
// Not a header column
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (headerCell._content.contains(this.getRootNode().activeElement)) {
|
|
95
|
+
// Something was focused inside the cell
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (this.$.scroller.hasAttribute('column-resizing')) {
|
|
100
|
+
// Resizing is in progress
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (!this._touchDevice) {
|
|
105
|
+
// Not a touch device
|
|
106
|
+
this._onTrackStart(e);
|
|
107
|
+
}
|
|
108
|
+
} else if (e.detail.state === 'track') {
|
|
109
|
+
this._onTrack(e);
|
|
110
|
+
} else if (e.detail.state === 'end') {
|
|
111
|
+
this._onTrackEnd(e);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** @private */
|
|
116
|
+
_onTrackStart(e) {
|
|
117
|
+
if (!this.columnReorderingAllowed) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Cancel reordering if there are draggable nodes on the event path
|
|
122
|
+
const path = e.composedPath && e.composedPath();
|
|
123
|
+
if (path && path.filter((node) => node.hasAttribute && node.hasAttribute('draggable'))[0]) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const headerCell = this._cellFromPoint(e.detail.x, e.detail.y);
|
|
128
|
+
if (!headerCell || headerCell.getAttribute('part').indexOf('header-cell') === -1) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
this.toggleAttribute('reordering', true);
|
|
133
|
+
this._draggedColumn = headerCell._column;
|
|
134
|
+
while (this._draggedColumn.parentElement.childElementCount === 1) {
|
|
135
|
+
// This is the only column in the group, drag the whole group instead
|
|
136
|
+
this._draggedColumn = this._draggedColumn.parentElement;
|
|
137
|
+
}
|
|
138
|
+
this._setSiblingsReorderStatus(this._draggedColumn, 'allowed');
|
|
139
|
+
this._draggedColumn._reorderStatus = 'dragging';
|
|
140
|
+
|
|
141
|
+
this._updateGhost(headerCell);
|
|
142
|
+
this._reorderGhost.style.visibility = 'visible';
|
|
143
|
+
this._updateGhostPosition(e.detail.x, this._touchDevice ? e.detail.y - 50 : e.detail.y);
|
|
144
|
+
this._autoScroller();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** @private */
|
|
148
|
+
_onTrack(e) {
|
|
149
|
+
if (!this._draggedColumn) {
|
|
150
|
+
// Reordering didn’t start. Skip this event.
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const targetCell = this._cellFromPoint(e.detail.x, e.detail.y);
|
|
155
|
+
if (!targetCell) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const targetColumn = this._getTargetColumn(targetCell, this._draggedColumn);
|
|
160
|
+
if (
|
|
161
|
+
this._isSwapAllowed(this._draggedColumn, targetColumn) &&
|
|
162
|
+
this._isSwappableByPosition(targetColumn, e.detail.x)
|
|
163
|
+
) {
|
|
164
|
+
this._swapColumnOrders(this._draggedColumn, targetColumn);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
this._updateGhostPosition(e.detail.x, this._touchDevice ? e.detail.y - 50 : e.detail.y);
|
|
168
|
+
this._lastDragClientX = e.detail.x;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** @private */
|
|
172
|
+
_onTrackEnd() {
|
|
173
|
+
if (!this._draggedColumn) {
|
|
174
|
+
// Reordering didn’t start. Skip this event.
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
this.toggleAttribute('reordering', false);
|
|
179
|
+
this._draggedColumn._reorderStatus = '';
|
|
180
|
+
this._setSiblingsReorderStatus(this._draggedColumn, '');
|
|
181
|
+
this._draggedColumn = null;
|
|
182
|
+
this._lastDragClientX = null;
|
|
183
|
+
this._reorderGhost.style.visibility = 'hidden';
|
|
184
|
+
|
|
185
|
+
this.dispatchEvent(
|
|
186
|
+
new CustomEvent('column-reorder', {
|
|
187
|
+
detail: {
|
|
188
|
+
columns: this._getColumnsInOrder()
|
|
189
|
+
}
|
|
190
|
+
})
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* @return {!Array<!GridColumn>}
|
|
196
|
+
* @protected
|
|
197
|
+
*/
|
|
198
|
+
_getColumnsInOrder() {
|
|
199
|
+
return this._columnTree
|
|
200
|
+
.slice(0)
|
|
201
|
+
.pop()
|
|
202
|
+
.filter((c) => !c.hidden)
|
|
203
|
+
.sort((b, a) => b._order - a._order);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* @param {number} x
|
|
208
|
+
* @param {number} y
|
|
209
|
+
* @return {HTMLElement | undefined}
|
|
210
|
+
* @protected
|
|
211
|
+
*/
|
|
212
|
+
_cellFromPoint(x, y) {
|
|
213
|
+
x = x || 0;
|
|
214
|
+
y = y || 0;
|
|
215
|
+
if (!this._draggedColumn) {
|
|
216
|
+
this.$.scroller.toggleAttribute('no-content-pointer-events', true);
|
|
217
|
+
}
|
|
218
|
+
const cell = this.shadowRoot.elementFromPoint(x, y);
|
|
219
|
+
this.$.scroller.toggleAttribute('no-content-pointer-events', false);
|
|
220
|
+
|
|
221
|
+
// Make sure the element is actually a cell
|
|
222
|
+
if (cell && cell._column) {
|
|
223
|
+
return cell;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* @param {number} eventClientX
|
|
229
|
+
* @param {number} eventClientY
|
|
230
|
+
* @protected
|
|
231
|
+
*/
|
|
232
|
+
_updateGhostPosition(eventClientX, eventClientY) {
|
|
233
|
+
const ghostRect = this._reorderGhost.getBoundingClientRect();
|
|
234
|
+
// // This is where we want to position the ghost
|
|
235
|
+
const targetLeft = eventClientX - ghostRect.width / 2;
|
|
236
|
+
const targetTop = eventClientY - ghostRect.height / 2;
|
|
237
|
+
// Current position
|
|
238
|
+
const _left = parseInt(this._reorderGhost._left || 0);
|
|
239
|
+
const _top = parseInt(this._reorderGhost._top || 0);
|
|
240
|
+
// Reposition the ghost
|
|
241
|
+
this._reorderGhost._left = _left - (ghostRect.left - targetLeft);
|
|
242
|
+
this._reorderGhost._top = _top - (ghostRect.top - targetTop);
|
|
243
|
+
this._reorderGhost.style.transform = `translate(${this._reorderGhost._left}px, ${this._reorderGhost._top}px)`;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* @param {!HTMLElement} cell
|
|
248
|
+
* @return {!HTMLElement}
|
|
249
|
+
* @protected
|
|
250
|
+
*/
|
|
251
|
+
_updateGhost(cell) {
|
|
252
|
+
const ghost = this._reorderGhost;
|
|
253
|
+
ghost.textContent = cell._content.innerText;
|
|
254
|
+
const style = window.getComputedStyle(cell);
|
|
255
|
+
[
|
|
256
|
+
'boxSizing',
|
|
257
|
+
'display',
|
|
258
|
+
'width',
|
|
259
|
+
'height',
|
|
260
|
+
'background',
|
|
261
|
+
'alignItems',
|
|
262
|
+
'padding',
|
|
263
|
+
'border',
|
|
264
|
+
'flex-direction',
|
|
265
|
+
'overflow'
|
|
266
|
+
].forEach((propertyName) => (ghost.style[propertyName] = style[propertyName]));
|
|
267
|
+
return ghost;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/** @private */
|
|
271
|
+
_updateOrders(columnTree, splices) {
|
|
272
|
+
if (columnTree === undefined || splices === undefined) {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Reset all column orders
|
|
277
|
+
columnTree[0].forEach((column) => (column._order = 0));
|
|
278
|
+
// Set order numbers to top-level columns
|
|
279
|
+
updateColumnOrders(columnTree[0], this._orderBaseScope, 0);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* @param {!GridColumn} column
|
|
284
|
+
* @param {string} status
|
|
285
|
+
* @protected
|
|
286
|
+
*/
|
|
287
|
+
_setSiblingsReorderStatus(column, status) {
|
|
288
|
+
Array.from(column.parentNode.children)
|
|
289
|
+
.filter((child) => /column/.test(child.localName) && this._isSwapAllowed(child, column))
|
|
290
|
+
.forEach((sibling) => (sibling._reorderStatus = status));
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/** @protected */
|
|
294
|
+
_autoScroller() {
|
|
295
|
+
if (this._lastDragClientX) {
|
|
296
|
+
const rightDiff = this._lastDragClientX - this.getBoundingClientRect().right + 50;
|
|
297
|
+
const leftDiff = this.getBoundingClientRect().left - this._lastDragClientX + 50;
|
|
298
|
+
|
|
299
|
+
if (rightDiff > 0) {
|
|
300
|
+
this.$.table.scrollLeft += rightDiff / 10;
|
|
301
|
+
} else if (leftDiff > 0) {
|
|
302
|
+
this.$.table.scrollLeft -= leftDiff / 10;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (this._draggedColumn) {
|
|
307
|
+
setTimeout(() => this._autoScroller(), 10);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* @param {GridColumn | undefined} column1
|
|
313
|
+
* @param {GridColumn | undefined} column2
|
|
314
|
+
* @return {boolean | undefined}
|
|
315
|
+
* @protected
|
|
316
|
+
*/
|
|
317
|
+
_isSwapAllowed(column1, column2) {
|
|
318
|
+
if (column1 && column2) {
|
|
319
|
+
const differentColumns = column1 !== column2;
|
|
320
|
+
const sameParent = column1.parentElement === column2.parentElement;
|
|
321
|
+
const sameFrozen = column1.frozen === column2.frozen;
|
|
322
|
+
return differentColumns && sameParent && sameFrozen;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* @param {!GridColumn} targetColumn
|
|
328
|
+
* @param {number} clientX
|
|
329
|
+
* @return {boolean}
|
|
330
|
+
* @protected
|
|
331
|
+
*/
|
|
332
|
+
_isSwappableByPosition(targetColumn, clientX) {
|
|
333
|
+
const targetCell = Array.from(this.$.header.querySelectorAll('tr:not([hidden]) [part~="cell"]')).filter((cell) =>
|
|
334
|
+
targetColumn.contains(cell._column)
|
|
335
|
+
)[0];
|
|
336
|
+
const sourceCellRect = this.$.header
|
|
337
|
+
.querySelector('tr:not([hidden]) [reorder-status=dragging]')
|
|
338
|
+
.getBoundingClientRect();
|
|
339
|
+
const targetRect = targetCell.getBoundingClientRect();
|
|
340
|
+
if (targetRect.left > sourceCellRect.left) {
|
|
341
|
+
return clientX > targetRect.right - sourceCellRect.width;
|
|
342
|
+
} else {
|
|
343
|
+
return clientX < targetRect.left + sourceCellRect.width;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* @param {!GridColumn} column1
|
|
349
|
+
* @param {!GridColumn} column2
|
|
350
|
+
* @protected
|
|
351
|
+
*/
|
|
352
|
+
_swapColumnOrders(column1, column2) {
|
|
353
|
+
const _order = column1._order;
|
|
354
|
+
column1._order = column2._order;
|
|
355
|
+
column2._order = _order;
|
|
356
|
+
this._updateLastFrozen();
|
|
357
|
+
this._updateFirstAndLastColumn();
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* @param {HTMLElement | undefined} targetCell
|
|
362
|
+
* @param {GridColumn} draggedColumn
|
|
363
|
+
* @return {GridColumn | undefined}
|
|
364
|
+
* @protected
|
|
365
|
+
*/
|
|
366
|
+
_getTargetColumn(targetCell, draggedColumn) {
|
|
367
|
+
if (targetCell && draggedColumn) {
|
|
368
|
+
let candidate = targetCell._column;
|
|
369
|
+
while (candidate.parentElement !== draggedColumn.parentElement && candidate !== this) {
|
|
370
|
+
candidate = candidate.parentElement;
|
|
371
|
+
}
|
|
372
|
+
if (candidate.parentElement === draggedColumn.parentElement) {
|
|
373
|
+
return candidate;
|
|
374
|
+
} else {
|
|
375
|
+
return targetCell._column;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Fired when the columns in the grid are reordered.
|
|
382
|
+
*
|
|
383
|
+
* @event column-reorder
|
|
384
|
+
* @param {Object} detail
|
|
385
|
+
* @param {Object} detail.columns the columns in the new order
|
|
386
|
+
*/
|
|
387
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2021 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { GestureEventListeners } from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
|
|
7
|
+
import { addListener } from '@polymer/polymer/lib/utils/gestures.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @polymerMixin
|
|
11
|
+
*/
|
|
12
|
+
export const ColumnResizingMixin = (superClass) =>
|
|
13
|
+
class ColumnResizingMixin extends GestureEventListeners(superClass) {
|
|
14
|
+
ready() {
|
|
15
|
+
super.ready();
|
|
16
|
+
const scroller = this.$.scroller;
|
|
17
|
+
addListener(scroller, 'track', this._onHeaderTrack.bind(this));
|
|
18
|
+
|
|
19
|
+
// Disallow scrolling while resizing
|
|
20
|
+
scroller.addEventListener('touchmove', (e) => scroller.hasAttribute('column-resizing') && e.preventDefault());
|
|
21
|
+
|
|
22
|
+
// Disable contextmenu on any resize separator.
|
|
23
|
+
scroller.addEventListener(
|
|
24
|
+
'contextmenu',
|
|
25
|
+
(e) => e.target.getAttribute('part') == 'resize-handle' && e.preventDefault()
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
// Disable native cell focus when resizing
|
|
29
|
+
scroller.addEventListener(
|
|
30
|
+
'mousedown',
|
|
31
|
+
(e) => e.target.getAttribute('part') === 'resize-handle' && e.preventDefault()
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** @private */
|
|
36
|
+
_onHeaderTrack(e) {
|
|
37
|
+
const handle = e.target;
|
|
38
|
+
if (handle.getAttribute('part') === 'resize-handle') {
|
|
39
|
+
const cell = handle.parentElement;
|
|
40
|
+
let column = cell._column;
|
|
41
|
+
|
|
42
|
+
this.$.scroller.toggleAttribute('column-resizing', true);
|
|
43
|
+
|
|
44
|
+
// Get the target column to resize
|
|
45
|
+
while (column.localName === 'vaadin-grid-column-group') {
|
|
46
|
+
column = Array.prototype.slice
|
|
47
|
+
.call(column._childColumns, 0)
|
|
48
|
+
.sort(function (a, b) {
|
|
49
|
+
return a._order - b._order;
|
|
50
|
+
})
|
|
51
|
+
.filter(function (column) {
|
|
52
|
+
return !column.hidden;
|
|
53
|
+
})
|
|
54
|
+
.pop();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const columnRowCells = Array.from(this.$.header.querySelectorAll('[part~="row"]:last-child [part~="cell"]'));
|
|
58
|
+
const targetCell = columnRowCells.filter((cell) => cell._column === column)[0];
|
|
59
|
+
// Resize the target column
|
|
60
|
+
if (targetCell.offsetWidth) {
|
|
61
|
+
const style = window.getComputedStyle(targetCell);
|
|
62
|
+
const minWidth =
|
|
63
|
+
10 +
|
|
64
|
+
parseInt(style.paddingLeft) +
|
|
65
|
+
parseInt(style.paddingRight) +
|
|
66
|
+
parseInt(style.borderLeftWidth) +
|
|
67
|
+
parseInt(style.borderRightWidth) +
|
|
68
|
+
parseInt(style.marginLeft) +
|
|
69
|
+
parseInt(style.marginRight);
|
|
70
|
+
const maxWidth =
|
|
71
|
+
targetCell.offsetWidth +
|
|
72
|
+
(this.__isRTL
|
|
73
|
+
? targetCell.getBoundingClientRect().left - e.detail.x
|
|
74
|
+
: e.detail.x - targetCell.getBoundingClientRect().right);
|
|
75
|
+
column.width = Math.max(minWidth, maxWidth) + 'px';
|
|
76
|
+
column.flexGrow = 0;
|
|
77
|
+
}
|
|
78
|
+
// Fix width and flex-grow for all preceding columns
|
|
79
|
+
columnRowCells
|
|
80
|
+
.sort(function (a, b) {
|
|
81
|
+
return a._column._order - b._column._order;
|
|
82
|
+
})
|
|
83
|
+
.forEach(function (cell, index, array) {
|
|
84
|
+
if (index < array.indexOf(targetCell)) {
|
|
85
|
+
cell._column.width = cell.offsetWidth + 'px';
|
|
86
|
+
cell._column.flexGrow = 0;
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
if (e.detail.state === 'end') {
|
|
91
|
+
this.$.scroller.toggleAttribute('column-resizing', false);
|
|
92
|
+
this.dispatchEvent(
|
|
93
|
+
new CustomEvent('column-resize', {
|
|
94
|
+
detail: { resizedColumn: column }
|
|
95
|
+
})
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Notify resize
|
|
100
|
+
this._resizeHandler();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Fired when a column in the grid is resized by the user.
|
|
106
|
+
*
|
|
107
|
+
* @event column-resize
|
|
108
|
+
* @param {Object} detail
|
|
109
|
+
* @param {Object} detail.resizedColumn the column that was resized
|
|
110
|
+
*/
|
|
111
|
+
};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { Grid } from './vaadin-grid.js';
|
|
2
|
+
|
|
3
|
+
import { GridBodyRenderer, GridColumnTextAlign, GridHeaderFooterRenderer, GridDefaultItem } from './interfaces';
|
|
4
|
+
|
|
5
|
+
declare function ColumnBaseMixin<TItem, T extends new (...args: any[]) => {}>(
|
|
6
|
+
base: T
|
|
7
|
+
): T & ColumnBaseMixinConstructor<TItem>;
|
|
8
|
+
|
|
9
|
+
export interface ColumnBaseMixinConstructor<TItem> {
|
|
10
|
+
new (...args: any[]): ColumnBaseMixin<TItem>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface ColumnBaseMixin<TItem> {
|
|
14
|
+
readonly _grid: Grid<TItem> | undefined;
|
|
15
|
+
readonly _allCells: HTMLElement[];
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* When set to true, the column is user-resizable.
|
|
19
|
+
*/
|
|
20
|
+
resizable: boolean | null | undefined;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* When true, the column is frozen. When a column inside of a column group is frozen,
|
|
24
|
+
* all of the sibling columns inside the group will get frozen also.
|
|
25
|
+
*/
|
|
26
|
+
frozen: boolean;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* When set to true, the cells for this column are hidden.
|
|
30
|
+
*/
|
|
31
|
+
hidden: boolean;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Text content to display in the header cell of the column.
|
|
35
|
+
*/
|
|
36
|
+
header: string | null | undefined;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Aligns the columns cell content horizontally.
|
|
40
|
+
* Supported values: "start", "center" and "end".
|
|
41
|
+
* @attr {start|center|end} text-align
|
|
42
|
+
*/
|
|
43
|
+
textAlign: GridColumnTextAlign | null | undefined;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Custom function for rendering the header content.
|
|
47
|
+
* Receives two arguments:
|
|
48
|
+
*
|
|
49
|
+
* - `root` The header cell content DOM element. Append your content to it.
|
|
50
|
+
* - `column` The `<vaadin-grid-column>` element.
|
|
51
|
+
*/
|
|
52
|
+
headerRenderer: GridHeaderFooterRenderer<TItem> | null | undefined;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Custom function for rendering the footer content.
|
|
56
|
+
* Receives two arguments:
|
|
57
|
+
*
|
|
58
|
+
* - `root` The footer cell content DOM element. Append your content to it.
|
|
59
|
+
* - `column` The `<vaadin-grid-column>` element.
|
|
60
|
+
*/
|
|
61
|
+
footerRenderer: GridHeaderFooterRenderer<TItem> | null | undefined;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* A `<vaadin-grid-column>` is used to configure how a column in `<vaadin-grid>`
|
|
66
|
+
* should look like.
|
|
67
|
+
*
|
|
68
|
+
* See [`<vaadin-grid>`](#/elements/vaadin-grid) documentation for instructions on how
|
|
69
|
+
* to configure the `<vaadin-grid-column>`.
|
|
70
|
+
*/
|
|
71
|
+
declare class GridColumn<TItem = GridDefaultItem> extends HTMLElement {
|
|
72
|
+
/**
|
|
73
|
+
* Width of the cells for this column.
|
|
74
|
+
*/
|
|
75
|
+
width: string | null | undefined;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Flex grow ratio for the cell widths. When set to 0, cell width is fixed.
|
|
79
|
+
* @attr {number} flex-grow
|
|
80
|
+
*/
|
|
81
|
+
flexGrow: number;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Custom function for rendering the cell content.
|
|
85
|
+
* Receives three arguments:
|
|
86
|
+
*
|
|
87
|
+
* - `root` The cell content DOM element. Append your content to it.
|
|
88
|
+
* - `column` The `<vaadin-grid-column>` element.
|
|
89
|
+
* - `model` The object with the properties related with
|
|
90
|
+
* the rendered item, contains:
|
|
91
|
+
* - `model.index` The index of the item.
|
|
92
|
+
* - `model.item` The item.
|
|
93
|
+
* - `model.expanded` Sublevel toggle state.
|
|
94
|
+
* - `model.level` Level of the tree represented with a horizontal offset of the toggle button.
|
|
95
|
+
* - `model.selected` Selected state.
|
|
96
|
+
* - `model.detailsOpened` Details opened state.
|
|
97
|
+
*/
|
|
98
|
+
renderer: GridBodyRenderer<TItem> | null | undefined;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Path to an item sub-property whose value gets displayed in the column body cells.
|
|
102
|
+
* The property name is also shown in the column header if an explicit header or renderer isn't defined.
|
|
103
|
+
*/
|
|
104
|
+
path: string | null | undefined;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Automatically sets the width of the column based on the column contents when this is set to `true`.
|
|
108
|
+
*
|
|
109
|
+
* For performance reasons the column width is calculated automatically only once when the grid items
|
|
110
|
+
* are rendered for the first time and the calculation only considers the rows which are currently
|
|
111
|
+
* rendered in DOM (a bit more than what is currently visible). If the grid is scrolled, or the cell
|
|
112
|
+
* content changes, the column width might not match the contents anymore.
|
|
113
|
+
*
|
|
114
|
+
* Hidden columns are ignored in the calculation and their widths are not automatically updated when
|
|
115
|
+
* you show a column that was initially hidden.
|
|
116
|
+
*
|
|
117
|
+
* You can manually trigger the auto sizing behavior again by calling `grid.recalculateColumnWidths()`.
|
|
118
|
+
*
|
|
119
|
+
* The column width may still grow larger when `flexGrow` is not 0.
|
|
120
|
+
* @attr {boolean} auto-width
|
|
121
|
+
*/
|
|
122
|
+
autoWidth: boolean;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
interface GridColumn<TItem = GridDefaultItem> extends ColumnBaseMixin<TItem> {}
|
|
126
|
+
|
|
127
|
+
declare global {
|
|
128
|
+
interface HTMLElementTagNameMap {
|
|
129
|
+
'vaadin-grid-column': GridColumn<GridDefaultItem>;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export { ColumnBaseMixin, GridColumn };
|