@vaadin/grid 22.0.0-alpha9 → 22.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +45 -26
  2. package/package.json +11 -11
  3. package/src/vaadin-grid-active-item-mixin.d.ts +5 -10
  4. package/src/vaadin-grid-array-data-provider-mixin.d.ts +4 -9
  5. package/src/vaadin-grid-column-group.d.ts +2 -2
  6. package/src/vaadin-grid-column-group.js +1 -1
  7. package/src/vaadin-grid-column-reordering-mixin.d.ts +4 -11
  8. package/src/vaadin-grid-column.d.ts +6 -9
  9. package/src/vaadin-grid-column.js +2 -2
  10. package/src/vaadin-grid-data-provider-mixin.d.ts +5 -10
  11. package/src/vaadin-grid-data-provider-mixin.js +1 -1
  12. package/src/vaadin-grid-drag-and-drop-mixin.d.ts +4 -9
  13. package/src/vaadin-grid-drag-and-drop-mixin.js +4 -3
  14. package/src/vaadin-grid-dynamic-columns-mixin.js +2 -2
  15. package/src/vaadin-grid-event-context-mixin.d.ts +4 -9
  16. package/src/vaadin-grid-filter-column.d.ts +1 -1
  17. package/src/vaadin-grid-filter-column.js +1 -1
  18. package/src/vaadin-grid-filter.js +3 -3
  19. package/src/vaadin-grid-keyboard-navigation-mixin.js +28 -15
  20. package/src/vaadin-grid-row-details-mixin.d.ts +4 -9
  21. package/src/vaadin-grid-scroll-mixin.d.ts +3 -8
  22. package/src/vaadin-grid-scroll-mixin.js +1 -1
  23. package/src/vaadin-grid-selection-column.d.ts +1 -1
  24. package/src/vaadin-grid-selection-column.js +34 -18
  25. package/src/vaadin-grid-selection-mixin.d.ts +4 -9
  26. package/src/vaadin-grid-sort-column.d.ts +1 -1
  27. package/src/vaadin-grid-sort-column.js +1 -1
  28. package/src/vaadin-grid-sort-mixin.d.ts +3 -8
  29. package/src/vaadin-grid-sorter.js +1 -1
  30. package/src/vaadin-grid-styles.js +1 -1
  31. package/src/vaadin-grid-styling-mixin.d.ts +6 -9
  32. package/src/vaadin-grid-tree-column.d.ts +1 -1
  33. package/src/vaadin-grid-tree-column.js +1 -1
  34. package/src/vaadin-grid-tree-toggle.js +1 -1
  35. package/src/vaadin-grid.d.ts +43 -52
  36. package/src/vaadin-grid.js +98 -79
  37. package/theme/lumo/vaadin-grid-sorter-styles.js +1 -1
  38. package/theme/lumo/vaadin-grid-styles.js +5 -1
  39. package/theme/lumo/vaadin-grid-tree-toggle-styles.js +1 -1
  40. package/theme/material/vaadin-grid-sorter-styles.js +1 -1
  41. package/theme/material/vaadin-grid-styles.js +5 -1
  42. package/theme/material/vaadin-grid-tree-toggle-styles.js +1 -1
@@ -3,39 +3,31 @@
3
3
  * Copyright (c) 2021 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { PolymerElement, html } from '@polymer/polymer/polymer-element.js';
6
+ import './vaadin-grid-column.js';
7
+ import './vaadin-grid-styles.js';
7
8
  import { beforeNextRender } from '@polymer/polymer/lib/utils/render-status.js';
9
+ import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
10
+ import { isAndroid, isFirefox, isIOS, isSafari, isTouch } from '@vaadin/component-base/src/browser-utils.js';
8
11
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
9
12
  import { processTemplates } from '@vaadin/component-base/src/templates.js';
13
+ import { Virtualizer } from '@vaadin/component-base/src/virtualizer.js';
10
14
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
11
- import { Virtualizer } from '@vaadin/virtual-list/src/virtualizer.js';
12
15
  import { A11yMixin } from './vaadin-grid-a11y-mixin.js';
13
16
  import { ActiveItemMixin } from './vaadin-grid-active-item-mixin.js';
14
17
  import { ArrayDataProviderMixin } from './vaadin-grid-array-data-provider-mixin.js';
18
+ import { ColumnReorderingMixin } from './vaadin-grid-column-reordering-mixin.js';
15
19
  import { ColumnResizingMixin } from './vaadin-grid-column-resizing-mixin.js';
16
20
  import { DataProviderMixin } from './vaadin-grid-data-provider-mixin.js';
21
+ import { DragAndDropMixin } from './vaadin-grid-drag-and-drop-mixin.js';
17
22
  import { DynamicColumnsMixin } from './vaadin-grid-dynamic-columns-mixin.js';
18
23
  import { EventContextMixin } from './vaadin-grid-event-context-mixin.js';
19
24
  import { FilterMixin } from './vaadin-grid-filter-mixin.js';
25
+ import { KeyboardNavigationMixin } from './vaadin-grid-keyboard-navigation-mixin.js';
20
26
  import { RowDetailsMixin } from './vaadin-grid-row-details-mixin.js';
21
27
  import { ScrollMixin } from './vaadin-grid-scroll-mixin.js';
22
28
  import { SelectionMixin } from './vaadin-grid-selection-mixin.js';
23
29
  import { SortMixin } from './vaadin-grid-sort-mixin.js';
24
30
  import { StylingMixin } from './vaadin-grid-styling-mixin.js';
25
- import { DragAndDropMixin } from './vaadin-grid-drag-and-drop-mixin.js';
26
- import { KeyboardNavigationMixin } from './vaadin-grid-keyboard-navigation-mixin.js';
27
- import { ColumnReorderingMixin } from './vaadin-grid-column-reordering-mixin.js';
28
- import './vaadin-grid-column.js';
29
- import './vaadin-grid-styles.js';
30
-
31
- const TOUCH_DEVICE = (() => {
32
- try {
33
- document.createEvent('TouchEvent');
34
- return true;
35
- } catch (e) {
36
- return false;
37
- }
38
- })();
39
31
 
40
32
  /**
41
33
  * `<vaadin-grid>` is a free, high quality data grid / data table Web Component. The content of the
@@ -147,20 +139,16 @@ const TOUCH_DEVICE = (() => {
147
139
  * in the second argument of the data provider callback:__
148
140
  *
149
141
  * ```javascript
150
- * grid.dataProvider = function(params, callback) {
151
- * const url = 'https://api.example/data' +
152
- * '?page=' + params.page + // the requested page index
153
- * '&per_page=' + params.pageSize; // number of items on the page
154
- * const xhr = new XMLHttpRequest();
155
- * xhr.onload = function() {
156
- * const response = JSON.parse(xhr.responseText);
157
- * callback(
158
- * response.employees, // requested page of items
159
- * response.totalSize // total number of items
160
- * );
161
- * };
162
- * xhr.open('GET', url, true);
163
- * xhr.send();
142
+ * grid.dataProvider = ({page, pageSize}, callback) => {
143
+ * // page: the requested page index
144
+ * // pageSize: number of items on one page
145
+ * const url = `https://api.example/data?page=${page}&per_page=${pageSize}`;
146
+ *
147
+ * fetch(url)
148
+ * .then((res) => res.json())
149
+ * .then(({ employees, totalSize }) => {
150
+ * callback(employees, totalSize);
151
+ * });
164
152
  * };
165
153
  * ```
166
154
  *
@@ -168,17 +156,12 @@ const TOUCH_DEVICE = (() => {
168
156
  *
169
157
  * ```javascript
170
158
  * grid.size = 200; // The total number of items
171
- * grid.dataProvider = function(params, callback) {
172
- * const url = 'https://api.example/data' +
173
- * '?page=' + params.page + // the requested page index
174
- * '&per_page=' + params.pageSize; // number of items on the page
175
- * const xhr = new XMLHttpRequest();
176
- * xhr.onload = function() {
177
- * const response = JSON.parse(xhr.responseText);
178
- * callback(response.employees);
179
- * };
180
- * xhr.open('GET', url, true);
181
- * xhr.send();
159
+ * grid.dataProvider = ({page, pageSize}, callback) => {
160
+ * const url = `https://api.example/data?page=${page}&per_page=${pageSize}`;
161
+ *
162
+ * fetch(url)
163
+ * .then((res) => res.json())
164
+ * .then((resJson) => callback(resJson.employees));
182
165
  * };
183
166
  * ```
184
167
  *
@@ -326,33 +309,31 @@ class Grid extends ElementMixin(
326
309
  /** @private */
327
310
  _safari: {
328
311
  type: Boolean,
329
- value: /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
312
+ value: isSafari
330
313
  },
331
314
 
332
315
  /** @private */
333
316
  _ios: {
334
317
  type: Boolean,
335
- value:
336
- (/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream) ||
337
- (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)
318
+ value: isIOS
338
319
  },
339
320
 
340
321
  /** @private */
341
322
  _firefox: {
342
323
  type: Boolean,
343
- value: navigator.userAgent.toLowerCase().indexOf('firefox') > -1
324
+ value: isFirefox
344
325
  },
345
326
 
346
327
  /** @private */
347
328
  _android: {
348
329
  type: Boolean,
349
- value: /android/i.test(navigator.userAgent)
330
+ value: isAndroid
350
331
  },
351
332
 
352
333
  /** @private */
353
334
  _touchDevice: {
354
335
  type: Boolean,
355
- value: TOUCH_DEVICE
336
+ value: isTouch
356
337
  },
357
338
 
358
339
  /**
@@ -512,6 +493,9 @@ class Grid extends ElementMixin(
512
493
 
513
494
  // If the focused cell's parent row got hidden by the size change, focus the corresponding new cell
514
495
  cellCoordinates && cell.parentElement.hidden && this.__focusBodyCell(cellCoordinates);
496
+
497
+ // Make sure the body has a tabbable element
498
+ this._resetKeyboardNavigation();
515
499
  }
516
500
  }
517
501
 
@@ -532,42 +516,72 @@ class Grid extends ElementMixin(
532
516
  }
533
517
  }
534
518
 
519
+ /** @private */
520
+ __getIntrinsicWidth(col) {
521
+ const initialWidth = col.width;
522
+ const initialFlexGrow = col.flexGrow;
523
+
524
+ col.width = 'auto';
525
+ col.flexGrow = 0;
526
+
527
+ // Note: _allCells only contains cells which are currently rendered in DOM
528
+ const width = col._allCells
529
+ .filter((cell) => {
530
+ // Exclude body cells that are out of the visible viewport
531
+ return !this.$.items.contains(cell) || this._isInViewport(cell.parentElement);
532
+ })
533
+ .reduce((width, cell) => {
534
+ // Add 1px buffer to the offset width to avoid too narrow columns (sub-pixel rendering)
535
+ return Math.max(width, cell.offsetWidth + 1);
536
+ }, 0);
537
+
538
+ col.flexGrow = initialFlexGrow;
539
+ col.width = initialWidth;
540
+
541
+ return width;
542
+ }
543
+
544
+ /** @private */
545
+ __getDistributedWidth(col, innerColumn) {
546
+ if (col == null || col === this) return 0;
547
+
548
+ const columnWidth = Math.max(this.__getIntrinsicWidth(col), this.__getDistributedWidth(col.parentElement, col));
549
+
550
+ // we're processing a regular grid-column and not a grid-column-group
551
+ if (!innerColumn) {
552
+ return columnWidth;
553
+ }
554
+
555
+ // At the end, the width of each vaadin-grid-column-group is determined by the sum of the width of its children.
556
+ // Here we determine how much space the vaadin-grid-column-group actually needs to render properly and then we distribute that space
557
+ // to its children, so when we actually do the summation it will be rendered properly.
558
+ // Check out vaadin-grid-column-group:_updateFlexAndWidth
559
+ const columnGroup = col;
560
+ const columnGroupWidth = columnWidth;
561
+ const sumOfWidthOfAllChildColumns = columnGroup._visibleChildColumns
562
+ .map((col) => this.__getIntrinsicWidth(col))
563
+ .reduce((sum, curr) => sum + curr, 0);
564
+
565
+ const extraNecessarySpaceForGridColumnGroup = Math.max(0, columnGroupWidth - sumOfWidthOfAllChildColumns);
566
+
567
+ // The distribution of the extra necessary space is done according to the intrinsic width of each child column.
568
+ // Lets say we need 100 pixels of extra space for the grid-column-group to render properly
569
+ // it has two grid-column children, |100px|300px| in total 400px
570
+ // the first column gets 25px of the additional space (100/400)*100 = 25
571
+ // the second column gets the 75px of the additional space (300/400)*100 = 75
572
+ const proportionOfExtraSpace = this.__getIntrinsicWidth(innerColumn) / sumOfWidthOfAllChildColumns;
573
+ const shareOfInnerColumnFromNecessaryExtraSpace = proportionOfExtraSpace * extraNecessarySpaceForGridColumnGroup;
574
+
575
+ return this.__getIntrinsicWidth(innerColumn) + shareOfInnerColumnFromNecessaryExtraSpace;
576
+ }
577
+
535
578
  /**
536
579
  * @param {!Array<!GridColumn>} cols the columns to auto size based on their content width
537
580
  * @private
538
581
  */
539
582
  _recalculateColumnWidths(cols) {
540
- // Note: The `cols.forEach()` loops below could be implemented as a single loop but this has been
541
- // split for performance reasons to batch these similar actions [write/read] together to avoid
542
- // unnecessary layout trashing.
543
-
544
- // [write] Set automatic width for all cells (breaks column alignment)
545
583
  cols.forEach((col) => {
546
- col.width = 'auto';
547
- col._origFlexGrow = col.flexGrow;
548
- col.flexGrow = 0;
549
- });
550
- // [read] Measure max cell width in each column
551
- cols.forEach((col) => {
552
- col._currentWidth = 0;
553
- // Note: _allCells only contains cells which are currently rendered in DOM
554
- col._allCells
555
- .filter((c) => {
556
- // Exclude body cells that are out of the visible viewport
557
- return !this.$.items.contains(c) || this._isInViewport(c.parentElement);
558
- })
559
- .forEach((c) => {
560
- // Add 1px buffer to the offset width to avoid too narrow columns (sub-pixel rendering)
561
- const cellWidth = c.offsetWidth + 1;
562
- col._currentWidth = Math.max(col._currentWidth, cellWidth);
563
- });
564
- });
565
- // [write] Set column widths to fit widest measured content
566
- cols.forEach((col) => {
567
- col.width = `${col._currentWidth}px`;
568
- col.flexGrow = col._origFlexGrow;
569
- col._currentWidth = undefined;
570
- col._origFlexGrow = undefined;
584
+ col.width = `${this.__getDistributedWidth(col)}px`;
571
585
  });
572
586
  }
573
587
 
@@ -791,6 +805,9 @@ class Grid extends ElementMixin(
791
805
  if (row.hidden !== !visibleRowCells.length) {
792
806
  row.hidden = !visibleRowCells.length;
793
807
  }
808
+
809
+ // Make sure the section has a tabbable element
810
+ this._resetKeyboardNavigation();
794
811
  }
795
812
 
796
813
  /** @private */
@@ -858,6 +875,7 @@ class Grid extends ElementMixin(
858
875
  this._a11yUpdateHeaderRows();
859
876
  this._a11yUpdateFooterRows();
860
877
  this.__updateFooterPositioning();
878
+ this.generateCellClassNames();
861
879
  }
862
880
 
863
881
  __updateFooterPositioning() {
@@ -884,7 +902,6 @@ class Grid extends ElementMixin(
884
902
 
885
903
  this._a11yUpdateRowLevel(row, model.level);
886
904
  this._a11yUpdateRowSelected(row, model.selected);
887
- this._a11yUpdateRowExpanded(row, model.expanded);
888
905
  this._a11yUpdateRowDetailsOpened(row, model.detailsOpened);
889
906
 
890
907
  row.toggleAttribute('expanded', model.expanded);
@@ -902,6 +919,8 @@ class Grid extends ElementMixin(
902
919
  });
903
920
 
904
921
  this._updateDetailsCellHeight(row);
922
+
923
+ this._a11yUpdateRowExpanded(row, model.expanded);
905
924
  }
906
925
 
907
926
  /** @private */
@@ -1,7 +1,7 @@
1
- import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
2
1
  import '@vaadin/vaadin-lumo-styles/color.js';
3
2
  import '@vaadin/vaadin-lumo-styles/style.js';
4
3
  import '@vaadin/vaadin-lumo-styles/spacing.js';
4
+ import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
5
5
 
6
6
  registerStyles(
7
7
  'vaadin-grid-sorter',
@@ -1,4 +1,3 @@
1
- import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
2
1
  import '@vaadin/vaadin-lumo-styles/color.js';
3
2
  import '@vaadin/vaadin-lumo-styles/font-icons.js';
4
3
  import '@vaadin/vaadin-lumo-styles/sizing.js';
@@ -6,6 +5,7 @@ import '@vaadin/vaadin-lumo-styles/spacing.js';
6
5
  import '@vaadin/vaadin-lumo-styles/style.js';
7
6
  import '@vaadin/vaadin-lumo-styles/typography.js';
8
7
  import '@vaadin/checkbox/theme/lumo/vaadin-checkbox.js';
8
+ import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
9
9
 
10
10
  registerStyles(
11
11
  'vaadin-grid',
@@ -60,6 +60,10 @@ registerStyles(
60
60
 
61
61
  /* Focus-ring */
62
62
 
63
+ [part~='row'] {
64
+ position: relative;
65
+ }
66
+
63
67
  [part~='row']:focus,
64
68
  [part~='cell']:focus {
65
69
  outline: none;
@@ -1,7 +1,7 @@
1
- import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
2
1
  import '@vaadin/vaadin-lumo-styles/color.js';
3
2
  import '@vaadin/vaadin-lumo-styles/spacing.js';
4
3
  import '@vaadin/vaadin-lumo-styles/style.js';
4
+ import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
5
5
 
6
6
  registerStyles(
7
7
  'vaadin-grid-tree-toggle',
@@ -1,6 +1,6 @@
1
- import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
2
1
  import '@vaadin/vaadin-material-styles/color.js';
3
2
  import '@vaadin/vaadin-material-styles/font-icons.js';
3
+ import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
4
4
 
5
5
  registerStyles(
6
6
  'vaadin-grid-sorter',
@@ -1,6 +1,6 @@
1
- import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
2
1
  import '@vaadin/vaadin-material-styles/color.js';
3
2
  import '@vaadin/vaadin-material-styles/typography.js';
3
+ import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
4
4
 
5
5
  registerStyles(
6
6
  'vaadin-grid',
@@ -118,6 +118,10 @@ registerStyles(
118
118
 
119
119
  /* Keyboard navigation */
120
120
 
121
+ [part~='row'] {
122
+ position: relative;
123
+ }
124
+
121
125
  [part~='row']:focus,
122
126
  [part~='cell']:focus {
123
127
  outline: none;
@@ -1,7 +1,7 @@
1
- import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
2
1
  import '@vaadin/vaadin-material-styles/color.js';
3
2
  import '@vaadin/vaadin-material-styles/font-icons.js';
4
3
  import '@vaadin/vaadin-material-styles/typography.js';
4
+ import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
5
5
 
6
6
  registerStyles(
7
7
  'vaadin-grid-tree-toggle',