@vaadin/grid 23.3.25 → 23.4.0-alpha1
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/package.json +10 -10
- package/src/vaadin-grid-column.js +1 -1
- package/src/vaadin-grid-data-provider-mixin.js +1 -0
- package/src/vaadin-grid-keyboard-navigation-mixin.js +23 -5
- package/src/vaadin-grid-row-details-mixin.js +7 -0
- package/src/vaadin-grid-selection-column-base-mixin.d.ts +63 -0
- package/src/vaadin-grid-selection-column-base-mixin.js +342 -0
- package/src/vaadin-grid-selection-column.d.ts +3 -12
- package/src/vaadin-grid-selection-column.js +39 -122
- package/src/vaadin-grid.js +20 -13
- package/web-types.json +16 -195
- package/web-types.lit.json +6 -76
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/grid",
|
|
3
|
-
"version": "23.
|
|
3
|
+
"version": "23.4.0-alpha1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -46,17 +46,17 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
48
48
|
"@polymer/polymer": "^3.0.0",
|
|
49
|
-
"@vaadin/checkbox": "
|
|
50
|
-
"@vaadin/component-base": "
|
|
51
|
-
"@vaadin/lit-renderer": "
|
|
52
|
-
"@vaadin/text-field": "
|
|
53
|
-
"@vaadin/vaadin-lumo-styles": "
|
|
54
|
-
"@vaadin/vaadin-material-styles": "
|
|
55
|
-
"@vaadin/vaadin-themable-mixin": "
|
|
49
|
+
"@vaadin/checkbox": "23.4.0-alpha1",
|
|
50
|
+
"@vaadin/component-base": "23.4.0-alpha1",
|
|
51
|
+
"@vaadin/lit-renderer": "23.4.0-alpha1",
|
|
52
|
+
"@vaadin/text-field": "23.4.0-alpha1",
|
|
53
|
+
"@vaadin/vaadin-lumo-styles": "23.4.0-alpha1",
|
|
54
|
+
"@vaadin/vaadin-material-styles": "23.4.0-alpha1",
|
|
55
|
+
"@vaadin/vaadin-themable-mixin": "23.4.0-alpha1"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@esm-bundle/chai": "^4.3.4",
|
|
59
|
-
"@vaadin/polymer-legacy-adapter": "
|
|
59
|
+
"@vaadin/polymer-legacy-adapter": "23.4.0-alpha1",
|
|
60
60
|
"@vaadin/testing-helpers": "^0.3.2",
|
|
61
61
|
"lit": "^2.0.0",
|
|
62
62
|
"sinon": "^13.0.2"
|
|
@@ -65,5 +65,5 @@
|
|
|
65
65
|
"web-types.json",
|
|
66
66
|
"web-types.lit.json"
|
|
67
67
|
],
|
|
68
|
-
"gitHead": "
|
|
68
|
+
"gitHead": "a7cdbab591c62ee8dbc0e91fee877fbbf4b92bad"
|
|
69
69
|
}
|
|
@@ -437,7 +437,7 @@ export const ColumnBaseMixin = (superClass) =>
|
|
|
437
437
|
|
|
438
438
|
/** @private */
|
|
439
439
|
_textAlignChanged(textAlign) {
|
|
440
|
-
if (textAlign === undefined) {
|
|
440
|
+
if (textAlign === undefined || this._grid === undefined) {
|
|
441
441
|
return;
|
|
442
442
|
}
|
|
443
443
|
if (['start', 'end', 'center'].indexOf(textAlign) === -1) {
|
|
@@ -662,7 +662,7 @@ export const KeyboardNavigationMixin = (superClass) =>
|
|
|
662
662
|
// If the target focusable is tied to a column that is not visible,
|
|
663
663
|
// find the first visible column and update the target in order to
|
|
664
664
|
// prevent scrolling to the start of the row.
|
|
665
|
-
if (focusStepTarget &&
|
|
665
|
+
if (focusStepTarget && !this.__isHorizontallyInViewport(focusStepTarget)) {
|
|
666
666
|
const firstVisibleColumn = this._getColumnsInOrder().find((column) => this.__isColumnInViewport(column));
|
|
667
667
|
if (firstVisibleColumn) {
|
|
668
668
|
if (focusStepTarget === this._headerFocusable) {
|
|
@@ -688,9 +688,14 @@ export const KeyboardNavigationMixin = (superClass) =>
|
|
|
688
688
|
// Assume frozen columns to always be inside the viewport
|
|
689
689
|
return true;
|
|
690
690
|
}
|
|
691
|
+
return this.__isHorizontallyInViewport(column._sizerCell);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
/** @private */
|
|
695
|
+
__isHorizontallyInViewport(element) {
|
|
691
696
|
return (
|
|
692
|
-
|
|
693
|
-
|
|
697
|
+
element.offsetLeft + element.offsetWidth >= this._scrollLeft &&
|
|
698
|
+
element.offsetLeft <= this._scrollLeft + this.clientWidth
|
|
694
699
|
);
|
|
695
700
|
}
|
|
696
701
|
|
|
@@ -832,9 +837,12 @@ export const KeyboardNavigationMixin = (superClass) =>
|
|
|
832
837
|
}
|
|
833
838
|
|
|
834
839
|
if (cell) {
|
|
835
|
-
// Fire a public event for cell.
|
|
836
840
|
const context = this.getEventContext(e);
|
|
837
|
-
|
|
841
|
+
this.__pendingBodyCellFocus = this.loading && context.section === 'body';
|
|
842
|
+
if (!this.__pendingBodyCellFocus) {
|
|
843
|
+
// Fire a cell-focus event for the cell
|
|
844
|
+
cell.dispatchEvent(new CustomEvent('cell-focus', { bubbles: true, composed: true, detail: { context } }));
|
|
845
|
+
}
|
|
838
846
|
this._focusedCell = cell._focusButton || cell;
|
|
839
847
|
|
|
840
848
|
if (isKeyboardActive() && e.target === cell) {
|
|
@@ -848,6 +856,16 @@ export const KeyboardNavigationMixin = (superClass) =>
|
|
|
848
856
|
this._detectFocusedItemIndex(e);
|
|
849
857
|
}
|
|
850
858
|
|
|
859
|
+
/**
|
|
860
|
+
* @private
|
|
861
|
+
*/
|
|
862
|
+
__dispatchPendingBodyCellFocus() {
|
|
863
|
+
// If the body cell focus was pending, dispatch the event once loading is done
|
|
864
|
+
if (this.__pendingBodyCellFocus && this.shadowRoot.activeElement === this._itemsFocusable) {
|
|
865
|
+
this._itemsFocusable.dispatchEvent(new Event('focusin', { bubbles: true, composed: true }));
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
|
|
851
869
|
/**
|
|
852
870
|
* Get the focusable element depending on the current focus mode.
|
|
853
871
|
* It can be a row, a cell, or a focusable div inside a cell.
|
|
@@ -153,6 +153,13 @@ export const RowDetailsMixin = (superClass) =>
|
|
|
153
153
|
return;
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
+
this.__updateDetailsRowPadding(row, cell);
|
|
157
|
+
// Ensure the row has correct padding after frame (the resize observer might miss it)
|
|
158
|
+
requestAnimationFrame(() => this.__updateDetailsRowPadding(row, cell));
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** @private */
|
|
162
|
+
__updateDetailsRowPadding(row, cell) {
|
|
156
163
|
if (cell.hidden) {
|
|
157
164
|
row.style.removeProperty('padding-bottom');
|
|
158
165
|
} else {
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2016 - 2023 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import type { Constructor } from '@open-wc/dedupe-mixin';
|
|
7
|
+
|
|
8
|
+
export declare function GridSelectionColumnBaseMixin<TItem, T extends Constructor<HTMLElement>>(
|
|
9
|
+
base: T,
|
|
10
|
+
): Constructor<GridSelectionColumnBaseMixinClass<TItem>> & T;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A mixin that provides basic functionality for the
|
|
14
|
+
* `<vaadin-grid-selection-column>`. This includes properties, cell rendering,
|
|
15
|
+
* and overridable methods for handling changes to the selection state.
|
|
16
|
+
*
|
|
17
|
+
* **NOTE**: This mixin is re-used by the Flow component, and as such must not
|
|
18
|
+
* implement any selection state updates for the column element or the grid.
|
|
19
|
+
* Web component-specific selection state updates must be implemented in the
|
|
20
|
+
* `<vaadin-grid-selection-column>` itself, by overriding the protected methods
|
|
21
|
+
* provided by this mixin.
|
|
22
|
+
*
|
|
23
|
+
* @polymerMixin
|
|
24
|
+
*/
|
|
25
|
+
export declare class GridSelectionColumnBaseMixinClass<TItem> {
|
|
26
|
+
/**
|
|
27
|
+
* When true, all the items are selected.
|
|
28
|
+
* @attr {boolean} select-all
|
|
29
|
+
*/
|
|
30
|
+
selectAll: boolean;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* When true, the active gets automatically selected.
|
|
34
|
+
* @attr {boolean} auto-select
|
|
35
|
+
*/
|
|
36
|
+
autoSelect: boolean;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* When true, rows can be selected by dragging over the selection column.
|
|
40
|
+
* @attr {boolean} drag-select
|
|
41
|
+
*/
|
|
42
|
+
dragSelect: boolean;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Override to handle the user selecting all items.
|
|
46
|
+
*/
|
|
47
|
+
protected _selectAll(): void;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Override to handle the user deselecting all items.
|
|
51
|
+
*/
|
|
52
|
+
protected _deselectAll(): void;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Override to handle the user selecting an item.
|
|
56
|
+
*/
|
|
57
|
+
protected _selectItem(item: TItem): void;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Override to handle the user deselecting an item.
|
|
61
|
+
*/
|
|
62
|
+
protected _deselectItem(item: TItem): void;
|
|
63
|
+
}
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2016 - 2023 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { addListener } from '@vaadin/component-base/src/gestures.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A mixin that provides basic functionality for the
|
|
10
|
+
* `<vaadin-grid-selection-column>`. This includes properties, cell rendering,
|
|
11
|
+
* and overridable methods for handling changes to the selection state.
|
|
12
|
+
*
|
|
13
|
+
* **NOTE**: This mixin is re-used by the Flow component, and as such must not
|
|
14
|
+
* implement any selection state updates for the column element or the grid.
|
|
15
|
+
* Web component-specific selection state updates must be implemented in the
|
|
16
|
+
* `<vaadin-grid-selection-column>` itself, by overriding the protected methods
|
|
17
|
+
* provided by this mixin.
|
|
18
|
+
*
|
|
19
|
+
* @polymerMixin
|
|
20
|
+
*/
|
|
21
|
+
export const GridSelectionColumnBaseMixin = (superClass) =>
|
|
22
|
+
class GridSelectionColumnBaseMixin extends superClass {
|
|
23
|
+
static get properties() {
|
|
24
|
+
return {
|
|
25
|
+
/**
|
|
26
|
+
* Width of the cells for this column.
|
|
27
|
+
*/
|
|
28
|
+
width: {
|
|
29
|
+
type: String,
|
|
30
|
+
value: '58px',
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Flex grow ratio for the cell widths. When set to 0, cell width is fixed.
|
|
35
|
+
* @attr {number} flex-grow
|
|
36
|
+
* @type {number}
|
|
37
|
+
*/
|
|
38
|
+
flexGrow: {
|
|
39
|
+
type: Number,
|
|
40
|
+
value: 0,
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* When true, all the items are selected.
|
|
45
|
+
* @attr {boolean} select-all
|
|
46
|
+
* @type {boolean}
|
|
47
|
+
*/
|
|
48
|
+
selectAll: {
|
|
49
|
+
type: Boolean,
|
|
50
|
+
value: false,
|
|
51
|
+
notify: true,
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* When true, the active gets automatically selected.
|
|
56
|
+
* @attr {boolean} auto-select
|
|
57
|
+
* @type {boolean}
|
|
58
|
+
*/
|
|
59
|
+
autoSelect: {
|
|
60
|
+
type: Boolean,
|
|
61
|
+
value: false,
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* When true, rows can be selected by dragging over the selection column.
|
|
66
|
+
* @attr {boolean} drag-select
|
|
67
|
+
* @type {boolean}
|
|
68
|
+
*/
|
|
69
|
+
dragSelect: {
|
|
70
|
+
type: Boolean,
|
|
71
|
+
value: false,
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
/** @protected */
|
|
75
|
+
_indeterminate: Boolean,
|
|
76
|
+
|
|
77
|
+
/** @protected */
|
|
78
|
+
_selectAllHidden: Boolean,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
static get observers() {
|
|
83
|
+
return [
|
|
84
|
+
'_onHeaderRendererOrBindingChanged(_headerRenderer, _headerCell, path, header, selectAll, _indeterminate, _selectAllHidden)',
|
|
85
|
+
];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Renders the Select All checkbox to the header cell.
|
|
90
|
+
*
|
|
91
|
+
* @override
|
|
92
|
+
*/
|
|
93
|
+
_defaultHeaderRenderer(root, _column) {
|
|
94
|
+
let checkbox = root.firstElementChild;
|
|
95
|
+
if (!checkbox) {
|
|
96
|
+
checkbox = document.createElement('vaadin-checkbox');
|
|
97
|
+
checkbox.setAttribute('aria-label', 'Select All');
|
|
98
|
+
checkbox.classList.add('vaadin-grid-select-all-checkbox');
|
|
99
|
+
root.appendChild(checkbox);
|
|
100
|
+
// Add listener after appending, so we can skip the initial change event
|
|
101
|
+
checkbox.addEventListener('checked-changed', this.__onSelectAllCheckedChanged.bind(this));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const checked = this.__isChecked(this.selectAll, this._indeterminate);
|
|
105
|
+
checkbox.__rendererChecked = checked;
|
|
106
|
+
checkbox.checked = checked;
|
|
107
|
+
checkbox.hidden = this._selectAllHidden;
|
|
108
|
+
checkbox.indeterminate = this._indeterminate;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Renders the Select Row checkbox to the body cell.
|
|
113
|
+
*
|
|
114
|
+
* @override
|
|
115
|
+
*/
|
|
116
|
+
_defaultRenderer(root, _column, { item, selected }) {
|
|
117
|
+
let checkbox = root.firstElementChild;
|
|
118
|
+
if (!checkbox) {
|
|
119
|
+
checkbox = document.createElement('vaadin-checkbox');
|
|
120
|
+
checkbox.setAttribute('aria-label', 'Select Row');
|
|
121
|
+
root.appendChild(checkbox);
|
|
122
|
+
// Add listener after appending, so we can skip the initial change event
|
|
123
|
+
checkbox.addEventListener('checked-changed', this.__onSelectRowCheckedChanged.bind(this));
|
|
124
|
+
addListener(root, 'track', this.__onCellTrack.bind(this));
|
|
125
|
+
root.addEventListener('mousedown', this.__onCellMouseDown.bind(this));
|
|
126
|
+
root.addEventListener('click', this.__onCellClick.bind(this));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
checkbox.__item = item;
|
|
130
|
+
checkbox.__rendererChecked = selected;
|
|
131
|
+
checkbox.checked = selected;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Updates the select all state when the Select All checkbox is switched.
|
|
136
|
+
* The listener handles only user-fired events.
|
|
137
|
+
*
|
|
138
|
+
* @private
|
|
139
|
+
*/
|
|
140
|
+
__onSelectAllCheckedChanged(e) {
|
|
141
|
+
// Skip if the state is changed by the renderer.
|
|
142
|
+
if (e.target.checked === e.target.__rendererChecked) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (this._indeterminate || e.target.checked) {
|
|
147
|
+
this._selectAll();
|
|
148
|
+
} else {
|
|
149
|
+
this._deselectAll();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Selects or deselects the row when the Select Row checkbox is switched.
|
|
155
|
+
* The listener handles only user-fired events.
|
|
156
|
+
*
|
|
157
|
+
* @private
|
|
158
|
+
*/
|
|
159
|
+
__onSelectRowCheckedChanged(e) {
|
|
160
|
+
// Skip if the state is changed by the renderer.
|
|
161
|
+
if (e.target.checked === e.target.__rendererChecked) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (e.target.checked) {
|
|
166
|
+
this._selectItem(e.target.__item);
|
|
167
|
+
} else {
|
|
168
|
+
this._deselectItem(e.target.__item);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** @private */
|
|
173
|
+
__onCellTrack(event) {
|
|
174
|
+
if (!this.dragSelect) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
this.__dragCurrentY = event.detail.y;
|
|
178
|
+
this.__dragDy = event.detail.dy;
|
|
179
|
+
if (event.detail.state === 'start') {
|
|
180
|
+
const renderedRows = this._grid._getVisibleRows();
|
|
181
|
+
// Get the row where the drag started
|
|
182
|
+
const dragStartRow = renderedRows.find((row) => row.contains(event.currentTarget.assignedSlot));
|
|
183
|
+
// Whether to select or deselect the items on drag
|
|
184
|
+
this.__dragSelect = !this._grid._isSelected(dragStartRow._item);
|
|
185
|
+
// Store the index of the row where the drag started
|
|
186
|
+
this.__dragStartIndex = dragStartRow.index;
|
|
187
|
+
// Store the item of the row where the drag started
|
|
188
|
+
this.__dragStartItem = dragStartRow._item;
|
|
189
|
+
// Start the auto scroller
|
|
190
|
+
this.__dragAutoScroller();
|
|
191
|
+
} else if (event.detail.state === 'end') {
|
|
192
|
+
// If drag start and end stays within the same item, then toggle its state
|
|
193
|
+
if (this.__dragStartItem) {
|
|
194
|
+
if (this.__dragSelect) {
|
|
195
|
+
this._grid.selectItem(this.__dragStartItem);
|
|
196
|
+
} else {
|
|
197
|
+
this._grid.deselectItem(this.__dragStartItem);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
// Clear drag state after timeout, which allows preventing the
|
|
201
|
+
// subsequent click event if drag started and ended on the same item
|
|
202
|
+
setTimeout(() => {
|
|
203
|
+
this.__dragStartIndex = undefined;
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/** @private */
|
|
209
|
+
__onCellMouseDown(e) {
|
|
210
|
+
if (this.dragSelect) {
|
|
211
|
+
// Prevent text selection when starting to drag
|
|
212
|
+
e.preventDefault();
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** @private */
|
|
217
|
+
__onCellClick(e) {
|
|
218
|
+
if (this.__dragStartIndex !== undefined) {
|
|
219
|
+
// Stop the click event if drag was enabled. This click event should
|
|
220
|
+
// only occur if drag started and stopped on the same item. In that case
|
|
221
|
+
// the selection state has already been toggled on drag end, and we
|
|
222
|
+
// don't want to toggle it again from clicking the checkbox or changing
|
|
223
|
+
// the active item.
|
|
224
|
+
e.preventDefault();
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** @private */
|
|
229
|
+
__dragAutoScroller() {
|
|
230
|
+
if (this.__dragStartIndex === undefined) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
// Get the row being hovered over
|
|
234
|
+
const renderedRows = this._grid._getVisibleRows();
|
|
235
|
+
const hoveredRow = renderedRows.find((row) => {
|
|
236
|
+
const rowRect = row.getBoundingClientRect();
|
|
237
|
+
return this.__dragCurrentY >= rowRect.top && this.__dragCurrentY <= rowRect.bottom;
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// Get the index of the row being hovered over or the first/last
|
|
241
|
+
// visible row if hovering outside the grid
|
|
242
|
+
let hoveredIndex = hoveredRow ? hoveredRow.index : undefined;
|
|
243
|
+
const scrollableArea = this.__getScrollableArea();
|
|
244
|
+
if (this.__dragCurrentY < scrollableArea.top) {
|
|
245
|
+
hoveredIndex = this._grid._firstVisibleIndex;
|
|
246
|
+
} else if (this.__dragCurrentY > scrollableArea.bottom) {
|
|
247
|
+
hoveredIndex = this._grid._lastVisibleIndex;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (hoveredIndex !== undefined) {
|
|
251
|
+
// Select all items between the start and the current row
|
|
252
|
+
renderedRows.forEach((row) => {
|
|
253
|
+
if (
|
|
254
|
+
(hoveredIndex > this.__dragStartIndex && row.index >= this.__dragStartIndex && row.index <= hoveredIndex) ||
|
|
255
|
+
(hoveredIndex < this.__dragStartIndex && row.index <= this.__dragStartIndex && row.index >= hoveredIndex)
|
|
256
|
+
) {
|
|
257
|
+
if (this.__dragSelect) {
|
|
258
|
+
this._grid.selectItem(row._item);
|
|
259
|
+
} else {
|
|
260
|
+
this._grid.deselectItem(row._item);
|
|
261
|
+
}
|
|
262
|
+
this.__dragStartItem = undefined;
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Start scrolling in the top/bottom 15% of the scrollable area
|
|
268
|
+
const scrollTriggerArea = scrollableArea.height * 0.15;
|
|
269
|
+
// Maximum number of pixels to scroll per iteration
|
|
270
|
+
const maxScrollAmount = 10;
|
|
271
|
+
|
|
272
|
+
if (this.__dragDy < 0 && this.__dragCurrentY < scrollableArea.top + scrollTriggerArea) {
|
|
273
|
+
const dy = scrollableArea.top + scrollTriggerArea - this.__dragCurrentY;
|
|
274
|
+
const percentage = Math.min(1, dy / scrollTriggerArea);
|
|
275
|
+
this._grid.$.table.scrollTop -= percentage * maxScrollAmount;
|
|
276
|
+
}
|
|
277
|
+
if (this.__dragDy > 0 && this.__dragCurrentY > scrollableArea.bottom - scrollTriggerArea) {
|
|
278
|
+
const dy = this.__dragCurrentY - (scrollableArea.bottom - scrollTriggerArea);
|
|
279
|
+
const percentage = Math.min(1, dy / scrollTriggerArea);
|
|
280
|
+
this._grid.$.table.scrollTop += percentage * maxScrollAmount;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Schedule the next auto scroll
|
|
284
|
+
setTimeout(() => this.__dragAutoScroller(), 10);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Gets the scrollable area of the grid as a bounding client rect. The
|
|
289
|
+
* scrollable area is the bounding rect of the grid minus the header and
|
|
290
|
+
* footer.
|
|
291
|
+
*
|
|
292
|
+
* @private
|
|
293
|
+
*/
|
|
294
|
+
__getScrollableArea() {
|
|
295
|
+
const gridRect = this._grid.$.table.getBoundingClientRect();
|
|
296
|
+
const headerRect = this._grid.$.header.getBoundingClientRect();
|
|
297
|
+
const footerRect = this._grid.$.footer.getBoundingClientRect();
|
|
298
|
+
|
|
299
|
+
return {
|
|
300
|
+
top: gridRect.top + headerRect.height,
|
|
301
|
+
bottom: gridRect.bottom - footerRect.height,
|
|
302
|
+
left: gridRect.left,
|
|
303
|
+
right: gridRect.right,
|
|
304
|
+
height: gridRect.height - headerRect.height - footerRect.height,
|
|
305
|
+
width: gridRect.width,
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Override to handle the user selecting all items.
|
|
311
|
+
* @protected
|
|
312
|
+
*/
|
|
313
|
+
_selectAll() {}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Override to handle the user deselecting all items.
|
|
317
|
+
* @protected
|
|
318
|
+
*/
|
|
319
|
+
_deselectAll() {}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Override to handle the user selecting an item.
|
|
323
|
+
* @param {Object} item the item to select
|
|
324
|
+
* @protected
|
|
325
|
+
*/
|
|
326
|
+
_selectItem(_item) {}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Override to handle the user deselecting an item.
|
|
330
|
+
* @param {Object} item the item to deselect
|
|
331
|
+
* @protected
|
|
332
|
+
*/
|
|
333
|
+
_deselectItem(_item) {}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* IOS needs indeterminate + checked at the same time
|
|
337
|
+
* @private
|
|
338
|
+
*/
|
|
339
|
+
__isChecked(selectAll, indeterminate) {
|
|
340
|
+
return indeterminate || selectAll;
|
|
341
|
+
}
|
|
342
|
+
};
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { GridDefaultItem } from './vaadin-grid.js';
|
|
7
7
|
import { GridColumn } from './vaadin-grid-column.js';
|
|
8
|
+
import type { GridSelectionColumnBaseMixinClass } from './vaadin-grid-selection-column-base-mixin.js';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Fired when the `selectAll` property changes.
|
|
@@ -42,18 +43,6 @@ export interface GridSelectionColumnEventMap extends HTMLElementEventMap, GridSe
|
|
|
42
43
|
* @fires {CustomEvent} select-all-changed - Fired when the `selectAll` property changes.
|
|
43
44
|
*/
|
|
44
45
|
declare class GridSelectionColumn<TItem = GridDefaultItem> extends GridColumn<TItem> {
|
|
45
|
-
/**
|
|
46
|
-
* When true, all the items are selected.
|
|
47
|
-
* @attr {boolean} select-all
|
|
48
|
-
*/
|
|
49
|
-
selectAll: boolean;
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* When true, the active gets automatically selected.
|
|
53
|
-
* @attr {boolean} auto-select
|
|
54
|
-
*/
|
|
55
|
-
autoSelect: boolean;
|
|
56
|
-
|
|
57
46
|
addEventListener<K extends keyof GridSelectionColumnEventMap>(
|
|
58
47
|
type: K,
|
|
59
48
|
listener: (this: GridSelectionColumn<TItem>, ev: GridSelectionColumnEventMap[K]) => void,
|
|
@@ -67,6 +56,8 @@ declare class GridSelectionColumn<TItem = GridDefaultItem> extends GridColumn<TI
|
|
|
67
56
|
): void;
|
|
68
57
|
}
|
|
69
58
|
|
|
59
|
+
interface GridSelectionColumn<TItem = GridDefaultItem> extends GridSelectionColumnBaseMixinClass<TItem> {}
|
|
60
|
+
|
|
70
61
|
declare global {
|
|
71
62
|
interface HTMLElementTagNameMap {
|
|
72
63
|
'vaadin-grid-selection-column': GridSelectionColumn<GridDefaultItem>;
|