@vaadin/grid 25.0.0-beta3 → 25.0.0-beta5
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 +11 -11
- package/src/styles/vaadin-grid-base-styles.js +250 -234
- package/src/styles/vaadin-grid-tree-toggle-base-styles.js +9 -1
- package/src/vaadin-grid-a11y-mixin.js +29 -28
- package/src/vaadin-grid-active-item-mixin.js +1 -1
- package/src/vaadin-grid-column-group-mixin.js +2 -2
- package/src/vaadin-grid-column-mixin.js +2 -2
- package/src/vaadin-grid-column-reordering-mixin.js +1 -1
- package/src/vaadin-grid-column-resizing-mixin.js +3 -9
- package/src/vaadin-grid-drag-and-drop-mixin.js +1 -1
- package/src/vaadin-grid-event-context-mixin.js +2 -2
- package/src/vaadin-grid-helpers.js +11 -14
- package/src/vaadin-grid-keyboard-navigation-mixin.js +9 -8
- package/src/vaadin-grid-mixin.d.ts +1 -6
- package/src/vaadin-grid-mixin.js +57 -42
- package/src/vaadin-grid-row-details-mixin.js +4 -4
- package/src/vaadin-grid-scroll-mixin.js +19 -5
- package/src/vaadin-grid-sort-mixin.js +1 -1
- package/src/vaadin-grid-styling-mixin.d.ts +0 -35
- package/src/vaadin-grid-styling-mixin.js +3 -67
- package/src/vaadin-grid.d.ts +6 -0
- package/src/vaadin-grid.js +8 -2
- package/web-types.json +4 -15
- package/web-types.lit.json +4 -11
|
@@ -8,7 +8,7 @@ import { css } from 'lit';
|
|
|
8
8
|
|
|
9
9
|
export const gridTreeToggleStyles = css`
|
|
10
10
|
:host {
|
|
11
|
-
display: flex;
|
|
11
|
+
display: inline-flex;
|
|
12
12
|
max-width: 100%;
|
|
13
13
|
pointer-events: none;
|
|
14
14
|
}
|
|
@@ -35,6 +35,13 @@ export const gridTreeToggleStyles = css`
|
|
|
35
35
|
width: calc(var(--_level, 0) * var(--vaadin-grid-tree-toggle-level-offset, 16px));
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/* Baseline alignment */
|
|
39
|
+
#level-spacer::before {
|
|
40
|
+
content: '\\2003' / '';
|
|
41
|
+
display: inline-block;
|
|
42
|
+
width: 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
38
45
|
[part='toggle'] {
|
|
39
46
|
margin-inline-end: var(--vaadin-gap-s);
|
|
40
47
|
}
|
|
@@ -66,6 +73,7 @@ export const gridTreeToggleStyles = css`
|
|
|
66
73
|
display: block;
|
|
67
74
|
overflow: hidden;
|
|
68
75
|
text-overflow: ellipsis;
|
|
76
|
+
flex: 1;
|
|
69
77
|
}
|
|
70
78
|
|
|
71
79
|
@media (forced-colors: active) {
|
|
@@ -22,73 +22,74 @@ export const A11yMixin = (superClass) =>
|
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
24
|
static get observers() {
|
|
25
|
-
return ['
|
|
25
|
+
return ['__a11yUpdateGridSize(size, _columnTree, __emptyState)'];
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
/** @private */
|
|
29
|
-
|
|
29
|
+
__a11yGetHeaderRowCount(_columnTree) {
|
|
30
30
|
return _columnTree.filter((level) =>
|
|
31
31
|
level.some((col) => col.headerRenderer || (col.path && col.header !== null) || col.header),
|
|
32
32
|
).length;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/** @private */
|
|
36
|
-
|
|
36
|
+
__a11yGetFooterRowCount(_columnTree) {
|
|
37
37
|
return _columnTree.filter((level) => level.some((col) => col.footerRenderer)).length;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
/** @private */
|
|
41
|
-
|
|
41
|
+
__a11yUpdateGridSize(size, _columnTree, emptyState) {
|
|
42
42
|
if (size === undefined || _columnTree === undefined) {
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
const headerRowsCount = this.
|
|
47
|
-
const footerRowsCount = this.
|
|
46
|
+
const headerRowsCount = this.__a11yGetHeaderRowCount(_columnTree);
|
|
47
|
+
const footerRowsCount = this.__a11yGetFooterRowCount(_columnTree);
|
|
48
48
|
const bodyRowsCount = emptyState ? 1 : size;
|
|
49
49
|
const rowsCount = bodyRowsCount + headerRowsCount + footerRowsCount;
|
|
50
50
|
|
|
51
51
|
this.$.table.setAttribute('aria-rowcount', rowsCount);
|
|
52
52
|
|
|
53
53
|
const bodyColumns = _columnTree[_columnTree.length - 1];
|
|
54
|
+
|
|
54
55
|
// If no header and footer rows while the empty state is active, count as one column
|
|
55
56
|
// Otherwise, use the number of body columns, if present
|
|
56
57
|
const columnsCount = emptyState ? 1 : (rowsCount && bodyColumns && bodyColumns.length) || 0;
|
|
57
58
|
this.$.table.setAttribute('aria-colcount', columnsCount);
|
|
58
59
|
|
|
59
|
-
this.
|
|
60
|
-
this.
|
|
60
|
+
this.__a11yUpdateHeaderRows();
|
|
61
|
+
this.__a11yUpdateFooterRows();
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
/** @
|
|
64
|
-
|
|
64
|
+
/** @private */
|
|
65
|
+
__a11yUpdateHeaderRows() {
|
|
65
66
|
iterateChildren(this.$.header, (headerRow, index) => {
|
|
66
67
|
headerRow.setAttribute('aria-rowindex', index + 1);
|
|
67
68
|
});
|
|
68
69
|
}
|
|
69
70
|
|
|
70
|
-
/** @
|
|
71
|
-
|
|
71
|
+
/** @private */
|
|
72
|
+
__a11yUpdateFooterRows() {
|
|
72
73
|
iterateChildren(this.$.footer, (footerRow, index) => {
|
|
73
|
-
footerRow.setAttribute('aria-rowindex', this.
|
|
74
|
+
footerRow.setAttribute('aria-rowindex', this.__a11yGetHeaderRowCount(this._columnTree) + this.size + index + 1);
|
|
74
75
|
});
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
/**
|
|
78
79
|
* @param {!HTMLElement} row
|
|
79
80
|
* @param {number} index
|
|
80
|
-
* @
|
|
81
|
+
* @private
|
|
81
82
|
*/
|
|
82
|
-
|
|
83
|
-
row.setAttribute('aria-rowindex', index + this.
|
|
83
|
+
__a11yUpdateRowRowindex(row) {
|
|
84
|
+
row.setAttribute('aria-rowindex', row.index + this.__a11yGetHeaderRowCount(this._columnTree) + 1);
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
/**
|
|
87
88
|
* @param {!HTMLElement} row
|
|
88
89
|
* @param {boolean} selected
|
|
89
|
-
* @
|
|
90
|
+
* @private
|
|
90
91
|
*/
|
|
91
|
-
|
|
92
|
+
__a11yUpdateRowSelected(row, selected) {
|
|
92
93
|
// Jaws reads selection only for rows, NVDA only for cells
|
|
93
94
|
row.setAttribute('aria-selected', Boolean(selected));
|
|
94
95
|
iterateRowCells(row, (cell) => {
|
|
@@ -98,9 +99,9 @@ export const A11yMixin = (superClass) =>
|
|
|
98
99
|
|
|
99
100
|
/**
|
|
100
101
|
* @param {!HTMLElement} row
|
|
101
|
-
* @
|
|
102
|
+
* @private
|
|
102
103
|
*/
|
|
103
|
-
|
|
104
|
+
__a11yUpdateRowExpanded(row) {
|
|
104
105
|
const toggleCell = findTreeToggleCell(row);
|
|
105
106
|
if (this.__isRowExpandable(row)) {
|
|
106
107
|
row.setAttribute('aria-expanded', 'false');
|
|
@@ -123,9 +124,9 @@ export const A11yMixin = (superClass) =>
|
|
|
123
124
|
/**
|
|
124
125
|
* @param {!HTMLElement} row
|
|
125
126
|
* @param {number} level
|
|
126
|
-
* @
|
|
127
|
+
* @private
|
|
127
128
|
*/
|
|
128
|
-
|
|
129
|
+
__a11yUpdateRowLevel(row, level) {
|
|
129
130
|
// Set level for the expandable rows itself, and all the nested rows.
|
|
130
131
|
if (level > 0 || this.__isRowCollapsible(row) || this.__isRowExpandable(row)) {
|
|
131
132
|
row.setAttribute('aria-level', level + 1);
|
|
@@ -137,9 +138,9 @@ export const A11yMixin = (superClass) =>
|
|
|
137
138
|
/**
|
|
138
139
|
* @param {!HTMLElement} row
|
|
139
140
|
* @param {!HTMLElement} detailsCell
|
|
140
|
-
* @
|
|
141
|
+
* @private
|
|
141
142
|
*/
|
|
142
|
-
|
|
143
|
+
__a11ySetRowDetailsCell(row, detailsCell) {
|
|
143
144
|
iterateRowCells(row, (cell) => {
|
|
144
145
|
if (cell !== detailsCell) {
|
|
145
146
|
cell.setAttribute('aria-controls', detailsCell.id);
|
|
@@ -150,14 +151,14 @@ export const A11yMixin = (superClass) =>
|
|
|
150
151
|
/**
|
|
151
152
|
* @param {!HTMLElement} cell
|
|
152
153
|
* @param {number} colspan
|
|
153
|
-
* @
|
|
154
|
+
* @private
|
|
154
155
|
*/
|
|
155
|
-
|
|
156
|
+
__a11yUpdateCellColspan(cell, colspan) {
|
|
156
157
|
cell.setAttribute('aria-colspan', Number(colspan));
|
|
157
158
|
}
|
|
158
159
|
|
|
159
|
-
/** @
|
|
160
|
-
|
|
160
|
+
/** @private */
|
|
161
|
+
__a11yUpdateSorters() {
|
|
161
162
|
Array.from(this.querySelectorAll('vaadin-grid-sorter')).forEach((sorter) => {
|
|
162
163
|
let cellContent = sorter.parentNode;
|
|
163
164
|
while (cellContent && cellContent.localName !== 'vaadin-grid-cell-content') {
|
|
@@ -73,7 +73,7 @@ export const ActiveItemMixin = (superClass) =>
|
|
|
73
73
|
// No clicked cell available
|
|
74
74
|
!cell ||
|
|
75
75
|
// Cell is a details cell
|
|
76
|
-
cell.
|
|
76
|
+
cell.part.contains('details-cell') ||
|
|
77
77
|
// Cell is the empty state cell
|
|
78
78
|
cell === this.$.emptystatecell ||
|
|
79
79
|
// Cell content is focused
|
|
@@ -314,13 +314,13 @@ export const GridColumnGroupMixin = (superClass) =>
|
|
|
314
314
|
if (headerCell) {
|
|
315
315
|
headerCell.setAttribute('colspan', colSpan);
|
|
316
316
|
if (this._grid) {
|
|
317
|
-
this._grid.
|
|
317
|
+
this._grid.__a11yUpdateCellColspan(headerCell, colSpan);
|
|
318
318
|
}
|
|
319
319
|
}
|
|
320
320
|
if (footerCell) {
|
|
321
321
|
footerCell.setAttribute('colspan', colSpan);
|
|
322
322
|
if (this._grid) {
|
|
323
|
-
this._grid.
|
|
323
|
+
this._grid.__a11yUpdateCellColspan(footerCell, colSpan);
|
|
324
324
|
}
|
|
325
325
|
}
|
|
326
326
|
}
|
|
@@ -7,7 +7,7 @@ import { animationFrame } from '@vaadin/component-base/src/async.js';
|
|
|
7
7
|
import { Debouncer } from '@vaadin/component-base/src/debounce.js';
|
|
8
8
|
import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
|
|
9
9
|
import { get } from '@vaadin/component-base/src/path-utils.js';
|
|
10
|
-
import { updateCellState } from './vaadin-grid-helpers.js';
|
|
10
|
+
import { updateCellState, updatePart } from './vaadin-grid-helpers.js';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* @polymerMixin
|
|
@@ -518,7 +518,7 @@ export const ColumnBaseMixin = (superClass) =>
|
|
|
518
518
|
|
|
519
519
|
if (resizable) {
|
|
520
520
|
const handle = document.createElement('div');
|
|
521
|
-
handle
|
|
521
|
+
updatePart(handle, 'resize-handle', true);
|
|
522
522
|
cell.appendChild(handle);
|
|
523
523
|
}
|
|
524
524
|
}
|
|
@@ -134,7 +134,7 @@ export const ColumnReorderingMixin = (superClass) =>
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
const headerCell = this._cellFromPoint(e.detail.x, e.detail.y);
|
|
137
|
-
if (!headerCell || !headerCell.
|
|
137
|
+
if (!headerCell || !headerCell.part.contains('header-cell')) {
|
|
138
138
|
return;
|
|
139
139
|
}
|
|
140
140
|
|
|
@@ -20,22 +20,16 @@ export const ColumnResizingMixin = (superClass) =>
|
|
|
20
20
|
scroller.addEventListener('touchmove', (e) => scroller.hasAttribute('column-resizing') && e.preventDefault());
|
|
21
21
|
|
|
22
22
|
// Disable contextmenu on any resize separator.
|
|
23
|
-
scroller.addEventListener(
|
|
24
|
-
'contextmenu',
|
|
25
|
-
(e) => e.target.getAttribute('part') === 'resize-handle' && e.preventDefault(),
|
|
26
|
-
);
|
|
23
|
+
scroller.addEventListener('contextmenu', (e) => e.target.part.contains('resize-handle') && e.preventDefault());
|
|
27
24
|
|
|
28
25
|
// Disable native cell focus when resizing
|
|
29
|
-
scroller.addEventListener(
|
|
30
|
-
'mousedown',
|
|
31
|
-
(e) => e.target.getAttribute('part') === 'resize-handle' && e.preventDefault(),
|
|
32
|
-
);
|
|
26
|
+
scroller.addEventListener('mousedown', (e) => e.target.part.contains('resize-handle') && e.preventDefault());
|
|
33
27
|
}
|
|
34
28
|
|
|
35
29
|
/** @private */
|
|
36
30
|
_onHeaderTrack(e) {
|
|
37
31
|
const handle = e.target;
|
|
38
|
-
if (handle.
|
|
32
|
+
if (handle.part.contains('resize-handle')) {
|
|
39
33
|
const cell = handle.parentElement;
|
|
40
34
|
let column = cell._column;
|
|
41
35
|
|
|
@@ -447,7 +447,7 @@ export const DragAndDropMixin = (superClass) =>
|
|
|
447
447
|
return rows
|
|
448
448
|
.map((row) => {
|
|
449
449
|
return Array.from(row.children)
|
|
450
|
-
.filter((cell) => !cell.hidden && cell.
|
|
450
|
+
.filter((cell) => !cell.hidden && !cell.part.contains('details-cell'))
|
|
451
451
|
.sort((a, b) => {
|
|
452
452
|
return a._column._order > b._column._order ? 1 : -1;
|
|
453
453
|
})
|
|
@@ -40,8 +40,8 @@ export const EventContextMixin = (superClass) =>
|
|
|
40
40
|
return context;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
context.section = ['body', 'header', 'footer', 'details'].find(
|
|
44
|
-
|
|
43
|
+
context.section = ['body', 'header', 'footer', 'details'].find((section) =>
|
|
44
|
+
cell.part.contains(`${section}-cell`),
|
|
45
45
|
);
|
|
46
46
|
|
|
47
47
|
if (cell._column) {
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { microTask } from '@vaadin/component-base/src/async.js';
|
|
7
7
|
import { Debouncer } from '@vaadin/component-base/src/debounce.js';
|
|
8
|
-
import { addValueToAttribute, removeValueFromAttribute } from '@vaadin/component-base/src/dom-utils.js';
|
|
9
8
|
|
|
10
9
|
/**
|
|
11
10
|
* Returns the cells of the given row, excluding the details cell.
|
|
@@ -81,15 +80,13 @@ export function updateState(element, attribute, value) {
|
|
|
81
80
|
|
|
82
81
|
/**
|
|
83
82
|
* @param {!HTMLElement} element
|
|
84
|
-
* @param {boolean | string | null | undefined} value
|
|
85
83
|
* @param {string} part
|
|
84
|
+
* @param {boolean | string | null | undefined} value
|
|
86
85
|
*/
|
|
87
|
-
export function updatePart(element,
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
removeValueFromAttribute(element, 'part', part);
|
|
92
|
-
}
|
|
86
|
+
export function updatePart(element, part, value) {
|
|
87
|
+
element.classList.toggle(part, value || value === '');
|
|
88
|
+
element.part.toggle(part, value || value === '');
|
|
89
|
+
element.part.length === 0 && element.removeAttribute('part');
|
|
93
90
|
}
|
|
94
91
|
|
|
95
92
|
/**
|
|
@@ -99,7 +96,7 @@ export function updatePart(element, value, part) {
|
|
|
99
96
|
*/
|
|
100
97
|
export function updateCellsPart(cells, part, value) {
|
|
101
98
|
cells.forEach((cell) => {
|
|
102
|
-
updatePart(cell,
|
|
99
|
+
updatePart(cell, part, value);
|
|
103
100
|
});
|
|
104
101
|
}
|
|
105
102
|
|
|
@@ -117,7 +114,7 @@ export function updateBooleanRowStates(row, states) {
|
|
|
117
114
|
const rowPart = `${state}-row`;
|
|
118
115
|
|
|
119
116
|
// Row part attribute
|
|
120
|
-
updatePart(row,
|
|
117
|
+
updatePart(row, rowPart, value);
|
|
121
118
|
|
|
122
119
|
// Cells part attribute
|
|
123
120
|
updateCellsPart(cells, `${rowPart}-cell`, value);
|
|
@@ -140,14 +137,14 @@ export function updateStringRowStates(row, states) {
|
|
|
140
137
|
// remove previous part from row and cells if there was any
|
|
141
138
|
if (prevValue) {
|
|
142
139
|
const prevRowPart = `${state}-${prevValue}-row`;
|
|
143
|
-
updatePart(row,
|
|
140
|
+
updatePart(row, prevRowPart, false);
|
|
144
141
|
updateCellsPart(cells, `${prevRowPart}-cell`, false);
|
|
145
142
|
}
|
|
146
143
|
|
|
147
144
|
// set new part to rows and cells if there is a value
|
|
148
145
|
if (value) {
|
|
149
146
|
const rowPart = `${state}-${value}-row`;
|
|
150
|
-
updatePart(row,
|
|
147
|
+
updatePart(row, rowPart, value);
|
|
151
148
|
updateCellsPart(cells, `${rowPart}-cell`, value);
|
|
152
149
|
}
|
|
153
150
|
});
|
|
@@ -166,11 +163,11 @@ export function updateCellState(cell, attribute, value, part, oldPart) {
|
|
|
166
163
|
|
|
167
164
|
// Remove old part from the attribute
|
|
168
165
|
if (oldPart) {
|
|
169
|
-
updatePart(cell,
|
|
166
|
+
updatePart(cell, oldPart, false);
|
|
170
167
|
}
|
|
171
168
|
|
|
172
169
|
// Add new part to the cell attribute
|
|
173
|
-
updatePart(cell,
|
|
170
|
+
updatePart(cell, part || `${attribute}-cell`, value);
|
|
174
171
|
}
|
|
175
172
|
|
|
176
173
|
/**
|
|
@@ -6,7 +6,7 @@
|
|
|
6
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
|
-
import {
|
|
9
|
+
import { updatePart } from './vaadin-grid-helpers.js';
|
|
10
10
|
|
|
11
11
|
function isRow(element) {
|
|
12
12
|
return element instanceof HTMLTableRowElement;
|
|
@@ -169,11 +169,11 @@ export const KeyboardNavigationMixin = (superClass) =>
|
|
|
169
169
|
/** @private */
|
|
170
170
|
_focusedCellChanged(focusedCell, oldFocusedCell) {
|
|
171
171
|
if (oldFocusedCell) {
|
|
172
|
-
|
|
172
|
+
updatePart(oldFocusedCell, 'focused-cell', false);
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
if (focusedCell) {
|
|
176
|
-
|
|
176
|
+
updatePart(focusedCell, 'focused-cell', true);
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
|
|
@@ -603,7 +603,7 @@ export const KeyboardNavigationMixin = (superClass) =>
|
|
|
603
603
|
this._scrollHorizontallyToCell(dstCell);
|
|
604
604
|
}
|
|
605
605
|
|
|
606
|
-
dstCell.focus();
|
|
606
|
+
dstCell.focus({ preventScroll: true });
|
|
607
607
|
}
|
|
608
608
|
}
|
|
609
609
|
|
|
@@ -1016,8 +1016,9 @@ export const KeyboardNavigationMixin = (superClass) =>
|
|
|
1016
1016
|
const dstRow = dstCell.parentNode;
|
|
1017
1017
|
const dstCellIndex = Array.from(dstRow.children).indexOf(dstCell);
|
|
1018
1018
|
const tableRect = this.$.table.getBoundingClientRect();
|
|
1019
|
-
|
|
1020
|
-
|
|
1019
|
+
const scrollbarWidth = this.$.table.clientWidth - this.$.table.offsetWidth;
|
|
1020
|
+
let leftBoundary = tableRect.left - (this.__isRTL ? scrollbarWidth : 0);
|
|
1021
|
+
let rightBoundary = tableRect.right + (this.__isRTL ? 0 : scrollbarWidth);
|
|
1021
1022
|
for (let i = dstCellIndex - 1; i >= 0; i--) {
|
|
1022
1023
|
const cell = dstRow.children[i];
|
|
1023
1024
|
if (cell.hasAttribute('hidden') || isDetailsCell(cell)) {
|
|
@@ -1040,10 +1041,10 @@ export const KeyboardNavigationMixin = (superClass) =>
|
|
|
1040
1041
|
}
|
|
1041
1042
|
|
|
1042
1043
|
if (dstCellRect.left < leftBoundary) {
|
|
1043
|
-
this.$.table.scrollLeft +=
|
|
1044
|
+
this.$.table.scrollLeft += dstCellRect.left - leftBoundary;
|
|
1044
1045
|
}
|
|
1045
1046
|
if (dstCellRect.right > rightBoundary) {
|
|
1046
|
-
this.$.table.scrollLeft +=
|
|
1047
|
+
this.$.table.scrollLeft += dstCellRect.right - rightBoundary;
|
|
1047
1048
|
}
|
|
1048
1049
|
}
|
|
1049
1050
|
|
|
@@ -31,15 +31,10 @@ import type { GridRowDetailsRenderer, RowDetailsMixinClass } from './vaadin-grid
|
|
|
31
31
|
import type { ScrollMixinClass } from './vaadin-grid-scroll-mixin.js';
|
|
32
32
|
import type { SelectionMixinClass } from './vaadin-grid-selection-mixin.js';
|
|
33
33
|
import type { SortMixinClass } from './vaadin-grid-sort-mixin.js';
|
|
34
|
-
import type {
|
|
35
|
-
GridCellClassNameGenerator,
|
|
36
|
-
GridCellPartNameGenerator,
|
|
37
|
-
StylingMixinClass,
|
|
38
|
-
} from './vaadin-grid-styling-mixin.js';
|
|
34
|
+
import type { GridCellPartNameGenerator, StylingMixinClass } from './vaadin-grid-styling-mixin.js';
|
|
39
35
|
|
|
40
36
|
export {
|
|
41
37
|
GridBodyRenderer,
|
|
42
|
-
GridCellClassNameGenerator,
|
|
43
38
|
GridCellPartNameGenerator,
|
|
44
39
|
GridDataProvider,
|
|
45
40
|
GridDataProviderCallback,
|
package/src/vaadin-grid-mixin.js
CHANGED
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
iterateRowCells,
|
|
29
29
|
updateBooleanRowStates,
|
|
30
30
|
updateCellsPart,
|
|
31
|
+
updatePart,
|
|
31
32
|
updateState,
|
|
32
33
|
} from './vaadin-grid-helpers.js';
|
|
33
34
|
import { KeyboardNavigationMixin } from './vaadin-grid-keyboard-navigation-mixin.js';
|
|
@@ -353,9 +354,10 @@ export const GridMixin = (superClass) =>
|
|
|
353
354
|
const rows = [];
|
|
354
355
|
for (let i = 0; i < count; i++) {
|
|
355
356
|
const row = document.createElement('tr');
|
|
356
|
-
row.setAttribute('part', 'row body-row');
|
|
357
357
|
row.setAttribute('role', 'row');
|
|
358
358
|
row.setAttribute('tabindex', '-1');
|
|
359
|
+
updatePart(row, 'row', true);
|
|
360
|
+
updatePart(row, 'body-row', true);
|
|
359
361
|
if (this._columnTree) {
|
|
360
362
|
this.__initRow(row, this._columnTree[this._columnTree.length - 1], 'body', false, true);
|
|
361
363
|
}
|
|
@@ -502,7 +504,8 @@ export const GridMixin = (superClass) =>
|
|
|
502
504
|
}
|
|
503
505
|
column._cells.push(cell);
|
|
504
506
|
}
|
|
505
|
-
cell
|
|
507
|
+
updatePart(cell, 'cell', true);
|
|
508
|
+
updatePart(cell, 'body-cell', true);
|
|
506
509
|
cell.__parentRow = row;
|
|
507
510
|
// Cache the cell reference
|
|
508
511
|
row.__cells.push(cell);
|
|
@@ -532,7 +535,7 @@ export const GridMixin = (superClass) =>
|
|
|
532
535
|
row.appendChild(detailsCell);
|
|
533
536
|
// Cache the details cell reference
|
|
534
537
|
row.__detailsCell = detailsCell;
|
|
535
|
-
this.
|
|
538
|
+
this.__a11ySetRowDetailsCell(row, detailsCell);
|
|
536
539
|
detailsCell._vacant = false;
|
|
537
540
|
}
|
|
538
541
|
|
|
@@ -564,7 +567,8 @@ export const GridMixin = (superClass) =>
|
|
|
564
567
|
column._emptyCells.push(cell);
|
|
565
568
|
}
|
|
566
569
|
}
|
|
567
|
-
cell
|
|
570
|
+
updatePart(cell, 'cell', true);
|
|
571
|
+
updatePart(cell, `${section}-cell`, true);
|
|
568
572
|
}
|
|
569
573
|
|
|
570
574
|
if (!cell._content.parentElement) {
|
|
@@ -639,9 +643,19 @@ export const GridMixin = (superClass) =>
|
|
|
639
643
|
row.hidden = !visibleRowCells.length;
|
|
640
644
|
}
|
|
641
645
|
|
|
646
|
+
if (row.parentElement === this.$.header) {
|
|
647
|
+
this.$.table.toggleAttribute('has-header', this.$.header.querySelector('tr:not([hidden])'));
|
|
648
|
+
this.__updateHeaderFooterRowParts('header');
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
if (row.parentElement === this.$.footer) {
|
|
652
|
+
this.$.table.toggleAttribute('has-footer', this.$.footer.querySelector('tr:not([hidden])'));
|
|
653
|
+
this.__updateHeaderFooterRowParts('footer');
|
|
654
|
+
}
|
|
655
|
+
|
|
642
656
|
// Make sure the section has a tabbable element
|
|
643
657
|
this._resetKeyboardNavigation();
|
|
644
|
-
this.
|
|
658
|
+
this.__a11yUpdateGridSize(this.size, this._columnTree, this.__emptyState);
|
|
645
659
|
}
|
|
646
660
|
|
|
647
661
|
/** @private */
|
|
@@ -653,11 +667,6 @@ export const GridMixin = (superClass) =>
|
|
|
653
667
|
}
|
|
654
668
|
|
|
655
669
|
row.index = index;
|
|
656
|
-
|
|
657
|
-
this._updateRowOrderParts(row, index);
|
|
658
|
-
|
|
659
|
-
this._a11yUpdateRowRowindex(row, index);
|
|
660
|
-
|
|
661
670
|
this.__ensureRowItem(row);
|
|
662
671
|
this.__ensureRowHierarchy(row);
|
|
663
672
|
this.__updateRow(row);
|
|
@@ -670,17 +679,17 @@ export const GridMixin = (superClass) =>
|
|
|
670
679
|
}
|
|
671
680
|
|
|
672
681
|
/** @private */
|
|
673
|
-
|
|
682
|
+
__updateRowOrderParts(row) {
|
|
674
683
|
updateBooleanRowStates(row, {
|
|
675
|
-
first: index === 0,
|
|
676
|
-
last: index === this._flatSize - 1,
|
|
677
|
-
odd: index % 2 !== 0,
|
|
678
|
-
even: index % 2 === 0,
|
|
684
|
+
first: row.index === 0,
|
|
685
|
+
last: row.index === this._flatSize - 1,
|
|
686
|
+
odd: row.index % 2 !== 0,
|
|
687
|
+
even: row.index % 2 === 0,
|
|
679
688
|
});
|
|
680
689
|
}
|
|
681
690
|
|
|
682
691
|
/** @private */
|
|
683
|
-
|
|
692
|
+
__updateRowStateParts(row, { item, expanded, selected, detailsOpened }) {
|
|
684
693
|
updateBooleanRowStates(row, {
|
|
685
694
|
expanded,
|
|
686
695
|
collapsed: this.__isRowExpandable(row),
|
|
@@ -702,24 +711,22 @@ export const GridMixin = (superClass) =>
|
|
|
702
711
|
_renderColumnTree(columnTree) {
|
|
703
712
|
iterateChildren(this.$.items, (row) => {
|
|
704
713
|
this.__initRow(row, columnTree[columnTree.length - 1], 'body', false, true);
|
|
705
|
-
|
|
706
|
-
const model = this.__getRowModel(row);
|
|
707
|
-
this._updateRowOrderParts(row);
|
|
708
|
-
this._updateRowStateParts(row, model);
|
|
709
|
-
this._filterDragAndDrop(row, model);
|
|
714
|
+
this.__updateRow(row);
|
|
710
715
|
});
|
|
711
716
|
|
|
712
717
|
while (this.$.header.children.length < columnTree.length) {
|
|
713
718
|
const headerRow = document.createElement('tr');
|
|
714
|
-
headerRow.setAttribute('part', 'row');
|
|
715
719
|
headerRow.setAttribute('role', 'row');
|
|
716
720
|
headerRow.setAttribute('tabindex', '-1');
|
|
721
|
+
updatePart(headerRow, 'row', true);
|
|
722
|
+
updatePart(headerRow, 'header-row', true);
|
|
717
723
|
this.$.header.appendChild(headerRow);
|
|
718
724
|
|
|
719
725
|
const footerRow = document.createElement('tr');
|
|
720
|
-
footerRow.setAttribute('part', 'row');
|
|
721
726
|
footerRow.setAttribute('role', 'row');
|
|
722
727
|
footerRow.setAttribute('tabindex', '-1');
|
|
728
|
+
updatePart(footerRow, 'row', true);
|
|
729
|
+
updatePart(footerRow, 'footer-row', true);
|
|
723
730
|
this.$.footer.appendChild(footerRow);
|
|
724
731
|
}
|
|
725
732
|
while (this.$.header.children.length > columnTree.length) {
|
|
@@ -727,36 +734,43 @@ export const GridMixin = (superClass) =>
|
|
|
727
734
|
this.$.footer.removeChild(this.$.footer.firstElementChild);
|
|
728
735
|
}
|
|
729
736
|
|
|
730
|
-
iterateChildren(this.$.header, (headerRow, index
|
|
737
|
+
iterateChildren(this.$.header, (headerRow, index) => {
|
|
731
738
|
this.__initRow(headerRow, columnTree[index], 'header', index === columnTree.length - 1);
|
|
732
|
-
|
|
733
|
-
const cells = getBodyRowCells(headerRow);
|
|
734
|
-
updateCellsPart(cells, 'first-header-row-cell', index === 0);
|
|
735
|
-
updateCellsPart(cells, 'last-header-row-cell', index === rows.length - 1);
|
|
736
739
|
});
|
|
737
740
|
|
|
738
|
-
iterateChildren(this.$.footer, (footerRow, index
|
|
741
|
+
iterateChildren(this.$.footer, (footerRow, index) => {
|
|
739
742
|
this.__initRow(footerRow, columnTree[columnTree.length - 1 - index], 'footer', index === 0);
|
|
740
|
-
|
|
741
|
-
const cells = getBodyRowCells(footerRow);
|
|
742
|
-
updateCellsPart(cells, 'first-footer-row-cell', index === 0);
|
|
743
|
-
updateCellsPart(cells, 'last-footer-row-cell', index === rows.length - 1);
|
|
744
743
|
});
|
|
745
744
|
|
|
746
745
|
// Sizer rows
|
|
747
746
|
this.__initRow(this.$.sizer, columnTree[columnTree.length - 1]);
|
|
748
747
|
|
|
748
|
+
this.__updateHeaderFooterRowParts('header');
|
|
749
|
+
this.__updateHeaderFooterRowParts('footer');
|
|
749
750
|
this._resizeHandler();
|
|
750
751
|
this._frozenCellsChanged();
|
|
751
752
|
this._updateFirstAndLastColumn();
|
|
752
753
|
this._resetKeyboardNavigation();
|
|
753
|
-
this.
|
|
754
|
-
this.
|
|
755
|
-
this.generateCellClassNames();
|
|
754
|
+
this.__a11yUpdateHeaderRows();
|
|
755
|
+
this.__a11yUpdateFooterRows();
|
|
756
756
|
this.generateCellPartNames();
|
|
757
757
|
this.__updateHeaderAndFooter();
|
|
758
758
|
}
|
|
759
759
|
|
|
760
|
+
/** @private */
|
|
761
|
+
__updateHeaderFooterRowParts(section) {
|
|
762
|
+
const visibleRows = [...this.$[section].querySelectorAll('tr:not([hidden])')];
|
|
763
|
+
[...this.$[section].children].forEach((row) => {
|
|
764
|
+
updatePart(row, `first-${section}-row`, row === visibleRows.at(0));
|
|
765
|
+
updatePart(row, `last-${section}-row`, row === visibleRows.at(-1));
|
|
766
|
+
|
|
767
|
+
getBodyRowCells(row).forEach((cell) => {
|
|
768
|
+
updatePart(cell, `first-${section}-row-cell`, row === visibleRows.at(0));
|
|
769
|
+
updatePart(cell, `last-${section}-row-cell`, row === visibleRows.at(-1));
|
|
770
|
+
});
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
|
|
760
774
|
/**
|
|
761
775
|
* @param {!HTMLElement} row
|
|
762
776
|
* @param {boolean} loading
|
|
@@ -773,7 +787,6 @@ export const GridMixin = (superClass) =>
|
|
|
773
787
|
|
|
774
788
|
if (loading) {
|
|
775
789
|
// Run style generators for the loading row to have custom names cleared
|
|
776
|
-
this._generateCellClassNames(row);
|
|
777
790
|
this._generateCellPartNames(row);
|
|
778
791
|
}
|
|
779
792
|
}
|
|
@@ -783,6 +796,9 @@ export const GridMixin = (superClass) =>
|
|
|
783
796
|
* @private
|
|
784
797
|
*/
|
|
785
798
|
__updateRow(row) {
|
|
799
|
+
this.__a11yUpdateRowRowindex(row);
|
|
800
|
+
this.__updateRowOrderParts(row);
|
|
801
|
+
|
|
786
802
|
const item = this.__getRowItem(row);
|
|
787
803
|
if (item) {
|
|
788
804
|
this.__updateRowLoading(row, false);
|
|
@@ -796,12 +812,11 @@ export const GridMixin = (superClass) =>
|
|
|
796
812
|
|
|
797
813
|
this._toggleDetailsCell(row, model.detailsOpened);
|
|
798
814
|
|
|
799
|
-
this.
|
|
800
|
-
this.
|
|
815
|
+
this.__a11yUpdateRowLevel(row, model.level);
|
|
816
|
+
this.__a11yUpdateRowSelected(row, model.selected);
|
|
801
817
|
|
|
802
|
-
this.
|
|
818
|
+
this.__updateRowStateParts(row, model);
|
|
803
819
|
|
|
804
|
-
this._generateCellClassNames(row, model);
|
|
805
820
|
this._generateCellPartNames(row, model);
|
|
806
821
|
this._filterDragAndDrop(row, model);
|
|
807
822
|
this.__updateDragSourceParts(row, model);
|
|
@@ -818,7 +833,7 @@ export const GridMixin = (superClass) =>
|
|
|
818
833
|
|
|
819
834
|
this._updateDetailsCellHeight(row);
|
|
820
835
|
|
|
821
|
-
this.
|
|
836
|
+
this.__a11yUpdateRowExpanded(row, model.expanded);
|
|
822
837
|
}
|
|
823
838
|
|
|
824
839
|
/** @private */
|