@vaadin/grid 25.0.0-alpha9 → 25.0.0-beta2
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/all-imports.js +1 -1
- package/package.json +12 -15
- package/src/array-data-provider.js +3 -2
- package/src/styles/vaadin-grid-base-styles.js +256 -91
- package/src/styles/vaadin-grid-sorter-base-styles.js +15 -2
- package/src/styles/vaadin-grid-tree-toggle-base-styles.js +4 -4
- package/src/vaadin-grid-a11y-mixin.js +26 -10
- package/src/vaadin-grid-column-auto-width-mixin.js +6 -11
- package/src/vaadin-grid-column-mixin.d.ts +1 -0
- package/src/vaadin-grid-column-mixin.js +1 -16
- package/src/vaadin-grid-column-reordering-mixin.js +2 -2
- package/src/vaadin-grid-data-provider-mixin.js +15 -10
- package/src/vaadin-grid-drag-and-drop-mixin.js +1 -1
- package/src/vaadin-grid-event-context-mixin.d.ts +2 -0
- package/src/vaadin-grid-event-context-mixin.js +1 -0
- package/src/vaadin-grid-filter.js +1 -1
- package/src/vaadin-grid-helpers.js +9 -0
- package/src/vaadin-grid-keyboard-navigation-mixin.js +1 -5
- package/src/vaadin-grid-mixin.d.ts +1 -0
- package/src/vaadin-grid-mixin.js +36 -38
- package/src/vaadin-grid-resize-mixin.d.ts +10 -0
- package/src/vaadin-grid-resize-mixin.js +73 -0
- package/src/vaadin-grid-row-details-mixin.js +1 -5
- package/src/vaadin-grid-scroll-mixin.js +5 -87
- package/src/vaadin-grid-selection-column-base-mixin.d.ts +1 -1
- package/src/vaadin-grid-selection-column-base-mixin.js +1 -1
- package/src/vaadin-grid-selection-column.d.ts +2 -0
- package/src/vaadin-grid-selection-column.js +2 -1
- package/src/vaadin-grid-sort-column.d.ts +2 -0
- package/src/vaadin-grid-sorter.d.ts +3 -3
- package/src/vaadin-grid-sorter.js +4 -4
- package/src/vaadin-grid-tree-column-mixin.js +7 -8
- package/src/vaadin-grid-tree-toggle.d.ts +4 -4
- package/src/vaadin-grid-tree-toggle.js +5 -5
- package/src/vaadin-grid.d.ts +1 -0
- package/src/vaadin-grid.js +3 -1
- package/vaadin-grid-column-group.js +1 -1
- package/vaadin-grid-column.js +1 -1
- package/vaadin-grid-filter-column.js +1 -1
- package/vaadin-grid-filter.js +1 -1
- package/vaadin-grid-selection-column.js +1 -1
- package/vaadin-grid-sort-column.js +1 -1
- package/vaadin-grid-sorter.js +1 -1
- package/vaadin-grid-tree-column.js +1 -1
- package/vaadin-grid-tree-toggle.js +1 -1
- package/vaadin-grid.js +1 -1
- package/web-types.json +13 -13
- package/web-types.lit.json +12 -12
- package/src/styles/vaadin-grid-core-styles.d.ts +0 -8
- package/src/styles/vaadin-grid-core-styles.js +0 -388
- package/src/styles/vaadin-grid-filter-core-styles.d.ts +0 -8
- package/src/styles/vaadin-grid-filter-core-styles.js +0 -18
- package/src/styles/vaadin-grid-sorter-core-styles.d.ts +0 -8
- package/src/styles/vaadin-grid-sorter-core-styles.js +0 -61
- package/src/styles/vaadin-grid-tree-toggle-core-styles.d.ts +0 -8
- package/src/styles/vaadin-grid-tree-toggle-core-styles.js +0 -78
- package/theme/lumo/all-imports.d.ts +0 -11
- package/theme/lumo/all-imports.js +0 -11
- package/theme/lumo/vaadin-grid-column-group.d.ts +0 -1
- package/theme/lumo/vaadin-grid-column-group.js +0 -1
- package/theme/lumo/vaadin-grid-column.d.ts +0 -1
- package/theme/lumo/vaadin-grid-column.js +0 -1
- package/theme/lumo/vaadin-grid-filter-column.d.ts +0 -2
- package/theme/lumo/vaadin-grid-filter-column.js +0 -2
- package/theme/lumo/vaadin-grid-filter.d.ts +0 -2
- package/theme/lumo/vaadin-grid-filter.js +0 -2
- package/theme/lumo/vaadin-grid-selection-column.d.ts +0 -2
- package/theme/lumo/vaadin-grid-selection-column.js +0 -2
- package/theme/lumo/vaadin-grid-sort-column.d.ts +0 -2
- package/theme/lumo/vaadin-grid-sort-column.js +0 -2
- package/theme/lumo/vaadin-grid-sorter-styles.d.ts +0 -3
- package/theme/lumo/vaadin-grid-sorter-styles.js +0 -52
- package/theme/lumo/vaadin-grid-sorter.d.ts +0 -2
- package/theme/lumo/vaadin-grid-sorter.js +0 -2
- package/theme/lumo/vaadin-grid-styles.d.ts +0 -6
- package/theme/lumo/vaadin-grid-styles.js +0 -405
- package/theme/lumo/vaadin-grid-tree-column.d.ts +0 -2
- package/theme/lumo/vaadin-grid-tree-column.js +0 -2
- package/theme/lumo/vaadin-grid-tree-toggle-styles.d.ts +0 -3
- package/theme/lumo/vaadin-grid-tree-toggle-styles.js +0 -81
- package/theme/lumo/vaadin-grid-tree-toggle.d.ts +0 -2
- package/theme/lumo/vaadin-grid-tree-toggle.js +0 -2
- package/theme/lumo/vaadin-grid.d.ts +0 -2
- package/theme/lumo/vaadin-grid.js +0 -2
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Copyright (c) 2016 - 2025 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
|
-
import '@vaadin/component-base/src/style-props.js';
|
|
6
|
+
import '@vaadin/component-base/src/styles/style-props.js';
|
|
7
7
|
import { css } from 'lit';
|
|
8
8
|
|
|
9
9
|
export const gridTreeToggleStyles = css`
|
|
@@ -36,7 +36,7 @@ export const gridTreeToggleStyles = css`
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
[part='toggle'] {
|
|
39
|
-
margin-inline-end: var(--vaadin-gap-
|
|
39
|
+
margin-inline-end: var(--vaadin-gap-s);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
[part='toggle']::before {
|
|
@@ -45,7 +45,7 @@ export const gridTreeToggleStyles = css`
|
|
|
45
45
|
width: var(--vaadin-icon-size, 1lh);
|
|
46
46
|
height: var(--vaadin-icon-size, 1lh);
|
|
47
47
|
background: currentColor;
|
|
48
|
-
mask
|
|
48
|
+
mask: var(--_vaadin-icon-chevron-down) 50% / var(--vaadin-icon-visual-size, 100%) no-repeat;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
:host(:not([expanded])) [part='toggle']::before {
|
|
@@ -54,7 +54,7 @@ export const gridTreeToggleStyles = css`
|
|
|
54
54
|
|
|
55
55
|
@media (prefers-reduced-motion: no-preference) {
|
|
56
56
|
[part='toggle']::before {
|
|
57
|
-
transition: rotate 120ms;
|
|
57
|
+
transition: var(--_non-focused-row-none, rotate 120ms);
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Copyright (c) 2016 - 2025 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
|
-
import { iterateChildren, iterateRowCells } from './vaadin-grid-helpers.js';
|
|
6
|
+
import { findTreeToggleCell, iterateChildren, iterateRowCells } from './vaadin-grid-helpers.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* @polymerMixin
|
|
@@ -22,7 +22,7 @@ export const A11yMixin = (superClass) =>
|
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
24
|
static get observers() {
|
|
25
|
-
return ['_a11yUpdateGridSize(size, _columnTree)'];
|
|
25
|
+
return ['_a11yUpdateGridSize(size, _columnTree, __emptyState)'];
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
/** @private */
|
|
@@ -34,21 +34,27 @@ export const A11yMixin = (superClass) =>
|
|
|
34
34
|
|
|
35
35
|
/** @private */
|
|
36
36
|
_a11yGetFooterRowCount(_columnTree) {
|
|
37
|
-
return _columnTree.filter((level) => level.some((col) => col.
|
|
37
|
+
return _columnTree.filter((level) => level.some((col) => col.footerRenderer)).length;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
/** @private */
|
|
41
|
-
_a11yUpdateGridSize(size, _columnTree) {
|
|
41
|
+
_a11yUpdateGridSize(size, _columnTree, emptyState) {
|
|
42
42
|
if (size === undefined || _columnTree === undefined) {
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
const headerRowsCount = this._a11yGetHeaderRowCount(_columnTree);
|
|
47
|
+
const footerRowsCount = this._a11yGetFooterRowCount(_columnTree);
|
|
48
|
+
const bodyRowsCount = emptyState ? 1 : size;
|
|
49
|
+
const rowsCount = bodyRowsCount + headerRowsCount + footerRowsCount;
|
|
50
|
+
|
|
51
|
+
this.$.table.setAttribute('aria-rowcount', rowsCount);
|
|
52
|
+
|
|
46
53
|
const bodyColumns = _columnTree[_columnTree.length - 1];
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
);
|
|
51
|
-
this.$.table.setAttribute('aria-colcount', (bodyColumns && bodyColumns.length) || 0);
|
|
54
|
+
// If no header and footer rows while the empty state is active, count as one column
|
|
55
|
+
// Otherwise, use the number of body columns, if present
|
|
56
|
+
const columnsCount = emptyState ? 1 : (rowsCount && bodyColumns && bodyColumns.length) || 0;
|
|
57
|
+
this.$.table.setAttribute('aria-colcount', columnsCount);
|
|
52
58
|
|
|
53
59
|
this._a11yUpdateHeaderRows();
|
|
54
60
|
this._a11yUpdateFooterRows();
|
|
@@ -95,12 +101,22 @@ export const A11yMixin = (superClass) =>
|
|
|
95
101
|
* @protected
|
|
96
102
|
*/
|
|
97
103
|
_a11yUpdateRowExpanded(row) {
|
|
104
|
+
const toggleCell = findTreeToggleCell(row);
|
|
98
105
|
if (this.__isRowExpandable(row)) {
|
|
99
106
|
row.setAttribute('aria-expanded', 'false');
|
|
107
|
+
if (toggleCell) {
|
|
108
|
+
toggleCell.setAttribute('aria-expanded', 'false');
|
|
109
|
+
}
|
|
100
110
|
} else if (this.__isRowCollapsible(row)) {
|
|
101
111
|
row.setAttribute('aria-expanded', 'true');
|
|
112
|
+
if (toggleCell) {
|
|
113
|
+
toggleCell.setAttribute('aria-expanded', 'true');
|
|
114
|
+
}
|
|
102
115
|
} else {
|
|
103
116
|
row.removeAttribute('aria-expanded');
|
|
117
|
+
if (toggleCell) {
|
|
118
|
+
toggleCell.removeAttribute('aria-expanded');
|
|
119
|
+
}
|
|
104
120
|
}
|
|
105
121
|
}
|
|
106
122
|
|
|
@@ -132,7 +148,7 @@ export const A11yMixin = (superClass) =>
|
|
|
132
148
|
}
|
|
133
149
|
|
|
134
150
|
/**
|
|
135
|
-
* @param {!HTMLElement}
|
|
151
|
+
* @param {!HTMLElement} cell
|
|
136
152
|
* @param {number} colspan
|
|
137
153
|
* @protected
|
|
138
154
|
*/
|
|
@@ -30,14 +30,12 @@ export const ColumnAutoWidthMixin = (superClass) =>
|
|
|
30
30
|
];
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
33
|
+
/** @protected */
|
|
34
|
+
updated(props) {
|
|
35
|
+
super.updated(props);
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (e.animationName.indexOf('vaadin-grid-appear') === 0) {
|
|
37
|
+
// If the grid was hidden and is now visible
|
|
38
|
+
if (props.has('__hostVisible') && !props.get('__hostVisible')) {
|
|
41
39
|
this.__tryToRecalculateColumnWidthsIfPending();
|
|
42
40
|
}
|
|
43
41
|
}
|
|
@@ -137,10 +135,7 @@ export const ColumnAutoWidthMixin = (superClass) =>
|
|
|
137
135
|
return this.__getIntrinsicWidth(innerColumn) + shareOfInnerColumnFromNecessaryExtraSpace;
|
|
138
136
|
}
|
|
139
137
|
|
|
140
|
-
/**
|
|
141
|
-
* @param {!Array<!GridColumn>} cols the columns to auto size based on their content width
|
|
142
|
-
* @private
|
|
143
|
-
*/
|
|
138
|
+
/** @private */
|
|
144
139
|
_recalculateColumnWidths() {
|
|
145
140
|
// Flush to make sure DOM is up-to-date when measuring the column widths
|
|
146
141
|
this.__virtualizer.flush();
|
|
@@ -147,6 +147,7 @@ export declare class GridColumnMixinClass<
|
|
|
147
147
|
* - `model.level` Level of the tree represented with a horizontal offset of the toggle button.
|
|
148
148
|
* - `model.selected` Selected state.
|
|
149
149
|
* - `model.detailsOpened` Details opened state.
|
|
150
|
+
* - `model.hasChildren` Whether the item has children.
|
|
150
151
|
*/
|
|
151
152
|
renderer: GridBodyRenderer<TItem, Column> | null | undefined;
|
|
152
153
|
|
|
@@ -536,24 +536,8 @@ export const ColumnBaseMixin = (superClass) =>
|
|
|
536
536
|
return;
|
|
537
537
|
}
|
|
538
538
|
|
|
539
|
-
let textAlignFallback;
|
|
540
|
-
if (getComputedStyle(this._grid).direction === 'ltr') {
|
|
541
|
-
if (textAlign === 'start') {
|
|
542
|
-
textAlignFallback = 'left';
|
|
543
|
-
} else if (textAlign === 'end') {
|
|
544
|
-
textAlignFallback = 'right';
|
|
545
|
-
}
|
|
546
|
-
} else if (textAlign === 'start') {
|
|
547
|
-
textAlignFallback = 'right';
|
|
548
|
-
} else if (textAlign === 'end') {
|
|
549
|
-
textAlignFallback = 'left';
|
|
550
|
-
}
|
|
551
|
-
|
|
552
539
|
this._allCells.forEach((cell) => {
|
|
553
540
|
cell._content.style.textAlign = textAlign;
|
|
554
|
-
if (getComputedStyle(cell._content).textAlign !== textAlign) {
|
|
555
|
-
cell._content.style.textAlign = textAlignFallback;
|
|
556
|
-
}
|
|
557
541
|
});
|
|
558
542
|
}
|
|
559
543
|
|
|
@@ -885,6 +869,7 @@ export const GridColumnMixin = (superClass) =>
|
|
|
885
869
|
* - `model.level` Level of the tree represented with a horizontal offset of the toggle button.
|
|
886
870
|
* - `model.selected` Selected state.
|
|
887
871
|
* - `model.detailsOpened` Details opened state.
|
|
872
|
+
* - `model.hasChildren` Whether the item has children.
|
|
888
873
|
*
|
|
889
874
|
* @type {GridBodyRenderer | null | undefined}
|
|
890
875
|
*/
|
|
@@ -127,9 +127,9 @@ export const ColumnReorderingMixin = (superClass) =>
|
|
|
127
127
|
return;
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
// Cancel reordering if there are draggable nodes on the event path
|
|
130
|
+
// Cancel reordering if there are draggable nodes on the event path following this element
|
|
131
131
|
const path = e.composedPath && e.composedPath();
|
|
132
|
-
if (path && path.some((node) => node.
|
|
132
|
+
if (path && path.slice(0, Math.max(0, path.indexOf(this))).some((node) => node.draggable)) {
|
|
133
133
|
return;
|
|
134
134
|
}
|
|
135
135
|
|
|
@@ -181,6 +181,12 @@ export const DataProviderMixin = (superClass) =>
|
|
|
181
181
|
this.requestContentUpdate();
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
+
/** @private */
|
|
185
|
+
__getRowLevel(row) {
|
|
186
|
+
const { level } = this._dataProviderController.getFlatIndexContext(row.index);
|
|
187
|
+
return level;
|
|
188
|
+
}
|
|
189
|
+
|
|
184
190
|
/** @private */
|
|
185
191
|
__getRowItem(row) {
|
|
186
192
|
const { item } = this._dataProviderController.getFlatIndexContext(row.index);
|
|
@@ -216,6 +222,15 @@ export const DataProviderMixin = (superClass) =>
|
|
|
216
222
|
return this.__expandedKeys && this.__expandedKeys.has(this.getItemId(item));
|
|
217
223
|
}
|
|
218
224
|
|
|
225
|
+
/**
|
|
226
|
+
* @param {!GridItem} item
|
|
227
|
+
* @return {boolean}
|
|
228
|
+
* @protected
|
|
229
|
+
*/
|
|
230
|
+
_hasChildren(item) {
|
|
231
|
+
return this.itemHasChildrenPath && item && !!get(this.itemHasChildrenPath, item);
|
|
232
|
+
}
|
|
233
|
+
|
|
219
234
|
/** @private */
|
|
220
235
|
_expandedItemsChanged() {
|
|
221
236
|
this._dataProviderController.recalculateFlatSize();
|
|
@@ -254,16 +269,6 @@ export const DataProviderMixin = (superClass) =>
|
|
|
254
269
|
}
|
|
255
270
|
}
|
|
256
271
|
|
|
257
|
-
/**
|
|
258
|
-
* @param {number} index
|
|
259
|
-
* @return {number}
|
|
260
|
-
* @protected
|
|
261
|
-
*/
|
|
262
|
-
_getIndexLevel(index = 0) {
|
|
263
|
-
const { level } = this._dataProviderController.getFlatIndexContext(index);
|
|
264
|
-
return level;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
272
|
/** @protected */
|
|
268
273
|
_onDataProviderPageRequested() {
|
|
269
274
|
this._setLoading(true);
|
|
@@ -13,6 +13,7 @@ export interface GridEventContext<TItem> {
|
|
|
13
13
|
index?: number;
|
|
14
14
|
selected?: boolean;
|
|
15
15
|
detailsOpened?: boolean;
|
|
16
|
+
hasChildren?: boolean;
|
|
16
17
|
expanded?: boolean;
|
|
17
18
|
level?: number;
|
|
18
19
|
}
|
|
@@ -34,6 +35,7 @@ export declare class EventContextMixinClass<TItem> {
|
|
|
34
35
|
* - `detailsOpened`: whether the row details are open for the item
|
|
35
36
|
* - `expanded`: the expanded state of the tree toggle
|
|
36
37
|
* - `level`: the tree hierarchy level
|
|
38
|
+
* - `hasChildren`: whether the item has children
|
|
37
39
|
*
|
|
38
40
|
* The returned object is populated only when a grid cell, header, footer or row details is found in `event.composedPath()`.
|
|
39
41
|
* This means mostly mouse and keyboard events. If such a grid part is not found in the path, an empty object is returned.
|
|
@@ -21,6 +21,7 @@ export const EventContextMixin = (superClass) =>
|
|
|
21
21
|
* - `detailsOpened`: whether the row details are open for the item
|
|
22
22
|
* - `expanded`: the expanded state of the tree toggle
|
|
23
23
|
* - `level`: the tree hierarchy level
|
|
24
|
+
* - `hasChildren`: whether the item has children
|
|
24
25
|
*
|
|
25
26
|
* The returned object is populated only when a grid cell, header, footer or row details is found in `event.composedPath()`.
|
|
26
27
|
* This means mostly mouse and keyboard events. If such a grid part is not found in the path, an empty object is returned.
|
|
@@ -9,7 +9,7 @@ import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
|
9
9
|
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
10
10
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin';
|
|
11
11
|
import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
|
|
12
|
-
import { gridFilterStyles } from './styles/vaadin-grid-filter-
|
|
12
|
+
import { gridFilterStyles } from './styles/vaadin-grid-filter-base-styles.js';
|
|
13
13
|
import { GridFilterElementMixin } from './vaadin-grid-filter-element-mixin.js';
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -173,6 +173,15 @@ export function updateCellState(cell, attribute, value, part, oldPart) {
|
|
|
173
173
|
updatePart(cell, value, part || `${attribute}-cell`);
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
+
/**
|
|
177
|
+
* Finds the cell containing the tree toggle element
|
|
178
|
+
* @param {!HTMLElement} row
|
|
179
|
+
* @return {HTMLElement | null}
|
|
180
|
+
*/
|
|
181
|
+
export function findTreeToggleCell(row) {
|
|
182
|
+
return getBodyRowCells(row).find((cell) => cell._content.querySelector('vaadin-grid-tree-toggle'));
|
|
183
|
+
}
|
|
184
|
+
|
|
176
185
|
/**
|
|
177
186
|
* A helper for observing flattened child column list of an element.
|
|
178
187
|
*/
|
|
@@ -7,7 +7,6 @@ import { isKeyboardActive } from '@vaadin/a11y-base/src/focus-utils.js';
|
|
|
7
7
|
import { animationFrame } from '@vaadin/component-base/src/async.js';
|
|
8
8
|
import { Debouncer } from '@vaadin/component-base/src/debounce.js';
|
|
9
9
|
import { addValueToAttribute, removeValueFromAttribute } from '@vaadin/component-base/src/dom-utils.js';
|
|
10
|
-
import { get } from '@vaadin/component-base/src/path-utils.js';
|
|
11
10
|
|
|
12
11
|
function isRow(element) {
|
|
13
12
|
return element instanceof HTMLTableRowElement;
|
|
@@ -286,10 +285,7 @@ export const KeyboardNavigationMixin = (superClass) =>
|
|
|
286
285
|
|
|
287
286
|
/** @private */
|
|
288
287
|
__isRowExpandable(row) {
|
|
289
|
-
|
|
290
|
-
const item = row._item;
|
|
291
|
-
return !!(item && get(this.itemHasChildrenPath, item) && !this._isExpanded(item));
|
|
292
|
-
}
|
|
288
|
+
return this._hasChildren(row._item) && !this._isExpanded(row._item);
|
|
293
289
|
}
|
|
294
290
|
|
|
295
291
|
/** @private */
|
package/src/vaadin-grid-mixin.js
CHANGED
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
updateState,
|
|
32
32
|
} from './vaadin-grid-helpers.js';
|
|
33
33
|
import { KeyboardNavigationMixin } from './vaadin-grid-keyboard-navigation-mixin.js';
|
|
34
|
+
import { ResizeMixin } from './vaadin-grid-resize-mixin.js';
|
|
34
35
|
import { RowDetailsMixin } from './vaadin-grid-row-details-mixin.js';
|
|
35
36
|
import { ScrollMixin } from './vaadin-grid-scroll-mixin.js';
|
|
36
37
|
import { SelectionMixin } from './vaadin-grid-selection-mixin.js';
|
|
@@ -57,6 +58,7 @@ import { StylingMixin } from './vaadin-grid-styling-mixin.js';
|
|
|
57
58
|
* @mixes EventContextMixin
|
|
58
59
|
* @mixes StylingMixin
|
|
59
60
|
* @mixes DragAndDropMixin
|
|
61
|
+
* @mixes ResizeMixin
|
|
60
62
|
*/
|
|
61
63
|
export const GridMixin = (superClass) =>
|
|
62
64
|
class extends ColumnAutoWidthMixin(
|
|
@@ -73,7 +75,7 @@ export const GridMixin = (superClass) =>
|
|
|
73
75
|
FilterMixin(
|
|
74
76
|
ColumnReorderingMixin(
|
|
75
77
|
ColumnResizingMixin(
|
|
76
|
-
EventContextMixin(DragAndDropMixin(StylingMixin(TabindexMixin(superClass)))),
|
|
78
|
+
EventContextMixin(DragAndDropMixin(StylingMixin(TabindexMixin(ResizeMixin(superClass))))),
|
|
77
79
|
),
|
|
78
80
|
),
|
|
79
81
|
),
|
|
@@ -168,11 +170,6 @@ export const GridMixin = (superClass) =>
|
|
|
168
170
|
};
|
|
169
171
|
}
|
|
170
172
|
|
|
171
|
-
constructor() {
|
|
172
|
-
super();
|
|
173
|
-
this.addEventListener('animationend', this._onAnimationEnd);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
173
|
/** @private */
|
|
177
174
|
get _firstVisibleIndex() {
|
|
178
175
|
const firstVisibleItem = this.__getFirstVisibleItem();
|
|
@@ -256,24 +253,13 @@ export const GridMixin = (superClass) =>
|
|
|
256
253
|
scrollContainer: this.$.items,
|
|
257
254
|
scrollTarget: this.$.table,
|
|
258
255
|
reorderElements: true,
|
|
256
|
+
// Grid rows have a CSS-defined minimum height, so the virtualizer's height
|
|
257
|
+
// placeholder logic can be disabled. This helps save reflows which might
|
|
258
|
+
// otherwise be triggered by this logic because it reads the row height
|
|
259
|
+
// right after updating the rows' content.
|
|
260
|
+
__disableHeightPlaceholder: true,
|
|
259
261
|
});
|
|
260
262
|
|
|
261
|
-
new ResizeObserver(() =>
|
|
262
|
-
setTimeout(() => {
|
|
263
|
-
this.__updateColumnsBodyContentHidden();
|
|
264
|
-
}),
|
|
265
|
-
).observe(this.$.table);
|
|
266
|
-
|
|
267
|
-
const minHeightObserver = new ResizeObserver(() =>
|
|
268
|
-
setTimeout(() => {
|
|
269
|
-
this.__updateMinHeight();
|
|
270
|
-
}),
|
|
271
|
-
);
|
|
272
|
-
|
|
273
|
-
minHeightObserver.observe(this.$.header);
|
|
274
|
-
minHeightObserver.observe(this.$.items);
|
|
275
|
-
minHeightObserver.observe(this.$.footer);
|
|
276
|
-
|
|
277
263
|
this._tooltipController = new TooltipController(this);
|
|
278
264
|
this.addController(this._tooltipController);
|
|
279
265
|
this._tooltipController.setManual(true);
|
|
@@ -284,6 +270,31 @@ export const GridMixin = (superClass) =>
|
|
|
284
270
|
});
|
|
285
271
|
}
|
|
286
272
|
|
|
273
|
+
/** @protected */
|
|
274
|
+
updated(props) {
|
|
275
|
+
super.updated(props);
|
|
276
|
+
|
|
277
|
+
// If the grid was hidden and is now visible
|
|
278
|
+
if (props.has('__hostVisible') && !props.get('__hostVisible')) {
|
|
279
|
+
// Ensure header and footer have tabbable elements
|
|
280
|
+
this._resetKeyboardNavigation();
|
|
281
|
+
|
|
282
|
+
requestAnimationFrame(() => this.__scrollToPendingIndexes());
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (props.has('__headerRect') || props.has('__footerRect') || props.has('__itemsRect')) {
|
|
286
|
+
setTimeout(() => this.__updateMinHeight());
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (props.has('__tableRect')) {
|
|
290
|
+
setTimeout(() => this.__updateColumnsBodyContentHidden());
|
|
291
|
+
|
|
292
|
+
// Updating data can change the visibility of the scroll bar. Therefore,
|
|
293
|
+
// the scroll position has to be recalculated.
|
|
294
|
+
this.__updateHorizontalScrollPosition();
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
287
298
|
/** @private */
|
|
288
299
|
__getBodyCellCoordinates(cell) {
|
|
289
300
|
if (this.$.items.contains(cell) && cell.localName === 'td') {
|
|
@@ -630,6 +641,7 @@ export const GridMixin = (superClass) =>
|
|
|
630
641
|
|
|
631
642
|
// Make sure the section has a tabbable element
|
|
632
643
|
this._resetKeyboardNavigation();
|
|
644
|
+
this._a11yUpdateGridSize(this.size, this._columnTree, this.__emptyState);
|
|
633
645
|
}
|
|
634
646
|
|
|
635
647
|
/** @private */
|
|
@@ -815,21 +827,6 @@ export const GridMixin = (superClass) =>
|
|
|
815
827
|
this.__updateHorizontalScrollPosition();
|
|
816
828
|
}
|
|
817
829
|
|
|
818
|
-
/** @private */
|
|
819
|
-
_onAnimationEnd(e) {
|
|
820
|
-
// ShadyCSS applies scoping suffixes to animation names
|
|
821
|
-
if (e.animationName.indexOf('vaadin-grid-appear') === 0) {
|
|
822
|
-
e.stopPropagation();
|
|
823
|
-
|
|
824
|
-
// Ensure header and footer have tabbable elements
|
|
825
|
-
this._resetKeyboardNavigation();
|
|
826
|
-
|
|
827
|
-
requestAnimationFrame(() => {
|
|
828
|
-
this.__scrollToPendingIndexes();
|
|
829
|
-
});
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
|
|
833
830
|
/**
|
|
834
831
|
* @param {!HTMLTableRowElement} row
|
|
835
832
|
* @return {!GridItemModel}
|
|
@@ -839,9 +836,10 @@ export const GridMixin = (superClass) =>
|
|
|
839
836
|
return {
|
|
840
837
|
index: row.index,
|
|
841
838
|
item: row._item,
|
|
842
|
-
level: this.
|
|
839
|
+
level: this.__getRowLevel(row),
|
|
843
840
|
expanded: this._isExpanded(row._item),
|
|
844
841
|
selected: this._isSelected(row._item),
|
|
842
|
+
hasChildren: this._hasChildren(row._item),
|
|
845
843
|
detailsOpened: !!this.rowDetailsRenderer && this._isDetailsOpened(row._item),
|
|
846
844
|
};
|
|
847
845
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2016 - 2025 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 ResizeMixin<T extends Constructor<HTMLElement>>(base: T): Constructor<ResizeMixinClass> & T;
|
|
9
|
+
|
|
10
|
+
declare class ResizeMixinClass {}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2016 - 2025 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A mixin to observe size changes of the grid and its main parts.
|
|
9
|
+
*
|
|
10
|
+
* @polymerMixin
|
|
11
|
+
*/
|
|
12
|
+
export const ResizeMixin = (superClass) =>
|
|
13
|
+
class extends superClass {
|
|
14
|
+
static get properties() {
|
|
15
|
+
return {
|
|
16
|
+
/** @private */
|
|
17
|
+
__hostVisible: {
|
|
18
|
+
type: Boolean,
|
|
19
|
+
value: false,
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
/** @private */
|
|
23
|
+
__tableRect: Object,
|
|
24
|
+
|
|
25
|
+
/** @private */
|
|
26
|
+
__headerRect: Object,
|
|
27
|
+
|
|
28
|
+
/** @private */
|
|
29
|
+
__itemsRect: Object,
|
|
30
|
+
|
|
31
|
+
/** @private */
|
|
32
|
+
__footerRect: Object,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** @protected */
|
|
37
|
+
ready() {
|
|
38
|
+
super.ready();
|
|
39
|
+
|
|
40
|
+
const resizeObserver = new ResizeObserver((entries) => {
|
|
41
|
+
const hostEntry = entries.findLast(({ target }) => target === this);
|
|
42
|
+
if (hostEntry) {
|
|
43
|
+
this.__hostVisible = this.checkVisibility();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const tableEntry = entries.findLast(({ target }) => target === this.$.table);
|
|
47
|
+
if (tableEntry) {
|
|
48
|
+
this.__tableRect = tableEntry.contentRect;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const headerEntry = entries.findLast(({ target }) => target === this.$.header);
|
|
52
|
+
if (headerEntry) {
|
|
53
|
+
this.__headerRect = headerEntry.contentRect;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const itemsEntry = entries.findLast(({ target }) => target === this.$.items);
|
|
57
|
+
if (itemsEntry) {
|
|
58
|
+
this.__itemsRect = itemsEntry.contentRect;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const footerEntry = entries.findLast(({ target }) => target === this.$.footer);
|
|
62
|
+
if (footerEntry) {
|
|
63
|
+
this.__footerRect = footerEntry.contentRect;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
resizeObserver.observe(this);
|
|
68
|
+
resizeObserver.observe(this.$.table);
|
|
69
|
+
resizeObserver.observe(this.$.header);
|
|
70
|
+
resizeObserver.observe(this.$.items);
|
|
71
|
+
resizeObserver.observe(this.$.footer);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
@@ -68,10 +68,6 @@ export const RowDetailsMixin = (superClass) =>
|
|
|
68
68
|
entries.forEach(({ target: cell }) => {
|
|
69
69
|
this._updateDetailsCellHeight(cell.parentElement);
|
|
70
70
|
});
|
|
71
|
-
|
|
72
|
-
// This workaround is needed until Safari also supports
|
|
73
|
-
// ResizeObserver.observe with {box: 'border-box'}
|
|
74
|
-
this.__virtualizer.__adapter._resizeHandler();
|
|
75
71
|
});
|
|
76
72
|
}
|
|
77
73
|
|
|
@@ -124,7 +120,7 @@ export const RowDetailsMixin = (superClass) =>
|
|
|
124
120
|
|
|
125
121
|
/**
|
|
126
122
|
* @param {!HTMLElement} row
|
|
127
|
-
* @param {
|
|
123
|
+
* @param {boolean} detailsOpened
|
|
128
124
|
* @protected
|
|
129
125
|
*/
|
|
130
126
|
_toggleDetailsCell(row, detailsOpened) {
|