@vaadin/vaadin-grid 5.8.4 → 5.9.3

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 CHANGED
@@ -15,7 +15,7 @@
15
15
  "repository": "vaadin/vaadin-grid",
16
16
  "homepage": "https://vaadin.com/components",
17
17
  "name": "@vaadin/vaadin-grid",
18
- "version": "5.8.4",
18
+ "version": "5.9.3",
19
19
  "main": "vaadin-grid.js",
20
20
  "author": "Vaadin Ltd",
21
21
  "license": "Apache-2.0",
@@ -45,32 +45,33 @@
45
45
  },
46
46
  "resolutions": {
47
47
  "@webcomponents/webcomponentsjs": "2.0.0",
48
- "es-abstract": "1.17.6",
49
- "@types/doctrine": "0.0.3",
50
48
  "inherits": "2.0.3",
51
49
  "samsam": "1.1.3",
52
50
  "supports-color": "3.1.2",
53
51
  "type-detect": "1.0.0"
54
52
  },
55
- "scripts": {
56
- "generate-typings": "gen-typescript-declarations --outDir . --verify"
57
- },
58
53
  "devDependencies": {
59
- "@webcomponents/webcomponentsjs": "^2.0.0",
60
- "wct-browser-legacy": "^1.0.1",
54
+ "@web-padawan/gen-typescript-declarations": "^1.6.2",
55
+ "web-component-tester": "6.9.2",
56
+ "@polymer/app-localize-behavior": "^3.0.0",
57
+ "@polymer/iron-ajax": "^3.0.0",
58
+ "@polymer/iron-component-page": "^4.0.0",
59
+ "@polymer/iron-image": "^3.0.0",
60
+ "@polymer/iron-list": "^3.0.0",
61
+ "@polymer/iron-media-query": "^3.0.0",
61
62
  "@polymer/iron-test-helpers": "^3.0.0",
62
- "@polymer/paper-input": "^3.0.0",
63
63
  "@polymer/paper-checkbox": "^3.0.0",
64
- "@polymer/iron-flex-layout": "^3.0.0",
65
- "@polymer/iron-image": "^3.0.0",
64
+ "@polymer/paper-input": "^3.0.0",
66
65
  "@polymer/paper-slider": "^3.0.0",
67
- "@polymer/iron-media-query": "^3.0.0",
68
- "@polymer/iron-component-page": "^4.0.0",
69
- "@polymer/iron-ajax": "^3.0.0",
70
- "@polymer/app-localize-behavior": "^3.0.0",
71
- "@polymer/iron-list": "^3.0.0",
72
- "@vaadin/vaadin-demo-helpers": "^3.1.0",
66
+ "@polymer/test-fixture": "^4.0.0",
73
67
  "@vaadin/vaadin-button": "^2.4.0",
74
- "@vaadin/vaadin-context-menu": "^4.5.0"
68
+ "@vaadin/vaadin-context-menu": "^4.5.0",
69
+ "@vaadin/vaadin-demo-helpers": "^3.1.0",
70
+ "@webcomponents/webcomponentsjs": "^2.0.0",
71
+ "wct-browser-legacy": "^1.0.1"
72
+ },
73
+ "scripts": {
74
+ "generate-typings": "gen-typescript-declarations --outDir . --verify",
75
+ "test": "wct --npm"
75
76
  }
76
77
  }
@@ -8,7 +8,6 @@ import { GestureEventListeners } from '@polymer/polymer/lib/mixins/gesture-event
8
8
  import { GridHelper } from './vaadin-grid-helpers.js';
9
9
  import { addListener } from '@polymer/polymer/lib/utils/gestures.js';
10
10
  import { dom } from '@polymer/polymer/lib/legacy/polymer.dom.js';
11
- import { useShadow } from '@polymer/polymer/lib/utils/settings.js';
12
11
 
13
12
  /**
14
13
  * @polymerMixin
@@ -214,15 +213,24 @@ export const ColumnReorderingMixin = superClass => class ColumnReorderingMixin e
214
213
  if (!this._draggedColumn) {
215
214
  this._toggleAttribute('no-content-pointer-events', true, this.$.scroller);
216
215
  }
216
+ // Workaround a ShadyDOM bug
217
+ this._reorderGhost.hidden = true;
218
+
217
219
  let cell;
218
- if (useShadow) {
220
+ if (this.shadowRoot.elementFromPoint) {
219
221
  cell = this.shadowRoot.elementFromPoint(x, y);
220
222
  } else {
221
223
  cell = document.elementFromPoint(x, y);
224
+ }
222
225
 
223
- // Workaround a FF58 bug
226
+ this._reorderGhost.hidden = false;
227
+
228
+ // Workaround FF58/ShadyDOM bugs
229
+ while (!cell._column && cell.parentElement) {
224
230
  if (cell.localName === 'vaadin-grid-cell-content') {
225
231
  cell = cell.assignedSlot.parentNode;
232
+ } else {
233
+ cell = cell.parentElement;
226
234
  }
227
235
 
228
236
  }
@@ -319,7 +319,15 @@ export const ColumnBaseMixin = superClass => class ColumnBaseMixin extends super
319
319
  }
320
320
 
321
321
  cells.forEach(cell => {
322
- const model = this._grid.__getRowModel(cell.parentElement);
322
+ const parent = cell.parentElement;
323
+
324
+ // When a column is made hidden and shown again, in some instances it breaks rendering of rows for grid
325
+ // this happens when parent element of cell is null, which might not be set correctly during rendering
326
+ // the newly shown column, this check simply avoid that case
327
+ if (!parent) {
328
+ return;
329
+ }
330
+ const model = this._grid.__getRowModel(parent);
323
331
 
324
332
  if (renderer) {
325
333
  cell._renderer = renderer;
@@ -360,7 +368,9 @@ export const ColumnBaseMixin = superClass => class ColumnBaseMixin extends super
360
368
  _setFooterTemplateOrRenderer(footerTemplate, footerRenderer, footerCell) {
361
369
  if ((footerTemplate || footerRenderer) && footerCell) {
362
370
  this.__setColumnTemplateOrRenderer(footerTemplate, footerRenderer, [footerCell]);
363
- this._grid.__updateHeaderFooterRowVisibility(footerCell.parentElement);
371
+ if (this._grid) {
372
+ this._grid.__updateHeaderFooterRowVisibility(footerCell.parentElement);
373
+ }
364
374
  }
365
375
  }
366
376
 
@@ -474,7 +484,7 @@ export const ColumnBaseMixin = superClass => class ColumnBaseMixin extends super
474
484
  }
475
485
  }
476
486
 
477
- if (headerCell) {
487
+ if (headerCell && this._grid) {
478
488
  this._grid.__updateHeaderFooterRowVisibility(headerCell.parentElement);
479
489
  }
480
490
  }
@@ -87,7 +87,7 @@ export const DragAndDropMixin = superClass => class DragAndDropMixin extends sup
87
87
 
88
88
  static get observers() {
89
89
  return [
90
- '_dragDropAccessChanged(rowsDraggable, dropMode, dragFilter, dropFilter)'
90
+ '_dragDropAccessChanged(rowsDraggable, dropMode, dragFilter, dropFilter, loading)'
91
91
  ];
92
92
  }
93
93
 
@@ -297,13 +297,17 @@ export const DragAndDropMixin = superClass => class DragAndDropMixin extends sup
297
297
 
298
298
  /** @private */
299
299
  __getViewportRows() {
300
- const headerBottom = this.$.header.getBoundingClientRect().bottom;
301
- const footerTop = this.$.footer.getBoundingClientRect().top;
302
- return Array.from(this.$.items.children)
303
- .filter(row => {
304
- const rowRect = row.getBoundingClientRect();
305
- return rowRect.bottom > headerBottom && rowRect.top < footerTop;
306
- });
300
+ // Workaround an IE11 bug where the `getBoundingClientRect` for header/footer
301
+ // might return incorrect values
302
+ this.$.header.style.outline = '0px solid transparent';
303
+ const scrollerRect = this.$.scroller.getBoundingClientRect();
304
+ const headerBottom = Math.max(this.$.header.getBoundingClientRect().bottom, scrollerRect.top);
305
+ const footerTop = Math.min(this.$.footer.getBoundingClientRect().top, scrollerRect.bottom);
306
+
307
+ return Array.from(this.$.items.children).filter((row) => {
308
+ const rowRect = row.getBoundingClientRect();
309
+ return rowRect.bottom > headerBottom && rowRect.top < footerTop;
310
+ });
307
311
  }
308
312
 
309
313
  /** @protected */
@@ -382,8 +386,9 @@ export const DragAndDropMixin = superClass => class DragAndDropMixin extends sup
382
386
  * @protected
383
387
  */
384
388
  _filterDragAndDrop(row, model) {
385
- const dragDisabled = !this.rowsDraggable || (this.dragFilter && !this.dragFilter(model));
386
- const dropDisabled = !this.dropMode || (this.dropFilter && !this.dropFilter(model));
389
+ const loading = this.loading || row.hasAttribute('loading');
390
+ const dragDisabled = !this.rowsDraggable || loading || (this.dragFilter && !this.dragFilter(model));
391
+ const dropDisabled = !this.dropMode || loading || (this.dropFilter && !this.dropFilter(model));
387
392
 
388
393
  const draggableElements = window.ShadyDOM
389
394
  ? [row]
@@ -532,6 +532,12 @@ export const KeyboardNavigationMixin = superClass => class KeyboardNavigationMix
532
532
  }
533
533
  // Inform cell content of the focus (used in <vaadin-grid-sorter>)
534
534
  cell._content.dispatchEvent(new CustomEvent('cell-focusin', {bubbles: false}));
535
+
536
+ // Fire a public event for cell focus.
537
+ const context = this.getEventContext(e);
538
+ cell.dispatchEvent(
539
+ new CustomEvent('cell-focus', {bubbles: true, composed: true, detail: {context: context}})
540
+ );
535
541
  }
536
542
 
537
543
  this._detectFocusedItemIndex(e);
@@ -738,4 +744,12 @@ export const KeyboardNavigationMixin = superClass => class KeyboardNavigationMix
738
744
  }
739
745
  return null;
740
746
  }
747
+
748
+ /**
749
+ * Fired when a cell is focused with click or keyboard navigation.
750
+ *
751
+ * Use context property of @see {@link GridCellFocusEvent} to get detail information about the event.
752
+ *
753
+ * @event cell-focus
754
+ */
741
755
  };
@@ -79,7 +79,13 @@ class GridScrollerElement extends PolymerIronList {
79
79
  this._scrollingToIndex = true;
80
80
  index = Math.min(Math.max(index, 0), this._effectiveSize - 1);
81
81
  this.$.table.scrollTop = index / this._effectiveSize * (this.$.table.scrollHeight - this.$.table.offsetHeight);
82
+
83
+ // We need to run the iron-list scroll handler here in order to recalculate the scaling from effective size to
84
+ // virtual size after changing the scroll position. However we don't want to trigger updates to the items / rows
85
+ // in this step, which could result in data provider requests for the previous viewport
86
+ this._preventItemUpdates = true;
82
87
  this._scrollHandler();
88
+ this._preventItemUpdates = false;
83
89
 
84
90
  if (this._accessIronListAPI(() => this._maxScrollTop) && this._virtualCount < this._effectiveSize) {
85
91
  this._adjustVirtualIndexOffset(1000000);
@@ -256,6 +262,10 @@ class GridScrollerElement extends PolymerIronList {
256
262
  * @protected
257
263
  */
258
264
  _assignModels(itemSet) {
265
+ // Skip here if internal flag for preventing item updates is set
266
+ if (this._preventItemUpdates) {
267
+ return;
268
+ }
259
269
  this._iterateItems((pidx, vidx) => {
260
270
  const el = this._physicalItems[pidx];
261
271
  this._toggleAttribute('hidden', vidx >= this._effectiveSize, el);
@@ -80,11 +80,7 @@ export const SelectionMixin = superClass => class SelectionMixin extends superCl
80
80
 
81
81
  /** @private */
82
82
  _selectedItemsChanged(e) {
83
- if (this.$.items.children.length && (e.path === 'selectedItems' || e.path === 'selectedItems.splices')) {
84
- Array.from(this.$.items.children).forEach(row => {
85
- this._updateItem(row, row._item);
86
- });
87
- }
83
+ this._assignModels();
88
84
  }
89
85
 
90
86
  /** @private */
@@ -255,7 +255,7 @@ import {timeOut, animationFrame} from '@polymer/polymer/lib/utils/async.js';
255
255
  * `reorder-status` | Reflects the status of a cell while columns are being reordered | cell
256
256
  * `frozen` | Frozen cell | cell
257
257
  * `last-frozen` | Last frozen cell | cell
258
- * * `first-column` | First visible cell on a row | cell
258
+ * `first-column` | First visible cell on a row | cell
259
259
  * `last-column` | Last visible cell on a row | cell
260
260
  * `selected` | Selected row | row
261
261
  * `expanded` | Expanded row | row
@@ -263,6 +263,7 @@ import {timeOut, animationFrame} from '@polymer/polymer/lib/utils/async.js';
263
263
  * `loading` | Row that is waiting for data from data provider | row
264
264
  * `odd` | Odd row | row
265
265
  * `first` | The first body row | row
266
+ * `last` | The last body row | row
266
267
  * `dragstart` | Set for one frame when drag of a row is starting. The value is a number when multiple rows are dragged | row
267
268
  * `dragover` | Set when the row is dragged over | row
268
269
  * `drag-disabled` | Set to a row that isn't available for dragging | row
@@ -239,7 +239,7 @@ const TOUCH_DEVICE = (() => {
239
239
  * `reorder-status` | Reflects the status of a cell while columns are being reordered | cell
240
240
  * `frozen` | Frozen cell | cell
241
241
  * `last-frozen` | Last frozen cell | cell
242
- * * `first-column` | First visible cell on a row | cell
242
+ * `first-column` | First visible cell on a row | cell
243
243
  * `last-column` | Last visible cell on a row | cell
244
244
  * `selected` | Selected row | row
245
245
  * `expanded` | Expanded row | row
@@ -247,6 +247,7 @@ const TOUCH_DEVICE = (() => {
247
247
  * `loading` | Row that is waiting for data from data provider | row
248
248
  * `odd` | Odd row | row
249
249
  * `first` | The first body row | row
250
+ * `last` | The last body row | row
250
251
  * `dragstart` | Set for one frame when drag of a row is starting. The value is a number when multiple rows are dragged | row
251
252
  * `dragover` | Set when the row is dragged over | row
252
253
  * `drag-disabled` | Set to a row that isn't available for dragging | row
@@ -322,7 +323,7 @@ class GridElement extends
322
323
  }
323
324
 
324
325
  static get version() {
325
- return '5.8.4';
326
+ return '5.9.3';
326
327
  }
327
328
 
328
329
  static get observers() {
@@ -461,37 +462,70 @@ class GridElement extends
461
462
  }
462
463
  }
463
464
 
465
+ /** @private */
466
+ __getIntrinsicWidth(col) {
467
+ const initialWidth = col.width;
468
+ const initialFlexGrow = col.flexGrow;
469
+
470
+ col.width = 'auto';
471
+ col.flexGrow = 0;
472
+
473
+ // Note: _allCells only contains cells which are currently rendered in DOM
474
+ const width = col._allCells
475
+ .reduce((width, cell) => {
476
+ // Add 1px buffer to the offset width to avoid too narrow columns (sub-pixel rendering)
477
+ return Math.max(width, cell.offsetWidth + 1);
478
+ }, 0);
479
+
480
+ col.flexGrow = initialFlexGrow;
481
+ col.width = initialWidth;
482
+
483
+ return width;
484
+ }
485
+
486
+ /** @private */
487
+ __getDistributedWidth(col, innerColumn) {
488
+ if (col == null || col === this) {
489
+ return 0;
490
+ }
491
+
492
+ const columnWidth = Math.max(this.__getIntrinsicWidth(col), this.__getDistributedWidth(col.parentElement, col));
493
+
494
+ // we're processing a regular grid-column and not a grid-column-group
495
+ if (!innerColumn) {
496
+ return columnWidth;
497
+ }
498
+
499
+ // At the end, the width of each vaadin-grid-column-group is determined by the sum of the width of its children.
500
+ // Here we determine how much space the vaadin-grid-column-group actually needs to render properly and then we distribute that space
501
+ // to its children, so when we actually do the summation it will be rendered properly.
502
+ // Check out vaadin-grid-column-group:_updateFlexAndWidth
503
+ const columnGroup = col;
504
+ const columnGroupWidth = columnWidth;
505
+ const sumOfWidthOfAllChildColumns = columnGroup._visibleChildColumns
506
+ .map((col) => this.__getIntrinsicWidth(col))
507
+ .reduce((sum, curr) => sum + curr, 0);
508
+
509
+ const extraNecessarySpaceForGridColumnGroup = Math.max(0, columnGroupWidth - sumOfWidthOfAllChildColumns);
510
+
511
+ // The distribution of the extra necessary space is done according to the intrinsic width of each child column.
512
+ // Lets say we need 100 pixels of extra space for the grid-column-group to render properly
513
+ // it has two grid-column children, |100px|300px| in total 400px
514
+ // the first column gets 25px of the additional space (100/400)*100 = 25
515
+ // the second column gets the 75px of the additional space (300/400)*100 = 75
516
+ const proportionOfExtraSpace = this.__getIntrinsicWidth(innerColumn) / sumOfWidthOfAllChildColumns;
517
+ const shareOfInnerColumnFromNecessaryExtraSpace = proportionOfExtraSpace * extraNecessarySpaceForGridColumnGroup;
518
+
519
+ return this.__getIntrinsicWidth(innerColumn) + shareOfInnerColumnFromNecessaryExtraSpace;
520
+ }
521
+
464
522
  /**
465
523
  * @param {!Array<!GridColumnElement>} cols the columns to auto size based on their content width
466
524
  * @private
467
525
  */
468
526
  _recalculateColumnWidths(cols) {
469
- // Note: The `cols.forEach()` loops below could be implemented as a single loop but this has been
470
- // split for performance reasons to batch these similar actions [write/read] together to avoid
471
- // unnecessary layout trashing.
472
-
473
- // [write] Set automatic width for all cells (breaks column alignment)
474
- cols.forEach(col => {
475
- col.width = 'auto';
476
- col._origFlexGrow = col.flexGrow;
477
- col.flexGrow = 0;
478
- });
479
- // [read] Measure max cell width in each column
480
- cols.forEach(col => {
481
- col._currentWidth = 0;
482
- // Note: _allCells only contains cells which are currently rendered in DOM
483
- col._allCells.forEach(c => {
484
- // Add 1px buffer to the offset width to avoid too narrow columns (sub-pixel rendering)
485
- const cellWidth = c.offsetWidth + 1;
486
- col._currentWidth = Math.max(col._currentWidth, cellWidth);
487
- });
488
- });
489
- // [write] Set column widths to fit widest measured content
490
- cols.forEach(col => {
491
- col.width = `${col._currentWidth}px`;
492
- col.flexGrow = col._origFlexGrow;
493
- col._currentWidth = undefined;
494
- col._origFlexGrow = undefined;
527
+ cols.forEach((col) => {
528
+ col.width = `${this.__getDistributedWidth(col)}px`;
495
529
  });
496
530
  }
497
531
 
@@ -731,6 +765,7 @@ class GridElement extends
731
765
  }
732
766
 
733
767
  this._toggleAttribute('first', index === 0, row);
768
+ this._toggleAttribute('last', index === this._effectiveSize - 1, row);
734
769
  this._toggleAttribute('odd', index % 2, row);
735
770
  this._a11yUpdateRowRowindex(row, index);
736
771
  this._getItem(index, row);
@@ -118,6 +118,10 @@ const $_documentContainer = html`<dom-module id="lumo-grid" theme-for="vaadin-gr
118
118
  margin-top: -1px;
119
119
  }
120
120
 
121
+ :host([all-rows-visible]) [part~="row"][last][dragover="below"] [part~="cell"]::after {
122
+ height: 1px;
123
+ }
124
+
121
125
  [part~="row"][dragover="above"] [part~="cell"]::after {
122
126
  top: auto;
123
127
  bottom: 100%;
@@ -161,6 +161,10 @@ const $_documentContainer = html`<dom-module id="material-grid" theme-for="vaadi
161
161
  margin-top: -1px;
162
162
  }
163
163
 
164
+ :host([all-rows-visible]) [part~="row"][last][dragover="below"] [part~="cell"]::after {
165
+ height: 1px;
166
+ }
167
+
164
168
  [part~="row"][dragover="above"] [part~="cell"]::after {
165
169
  top: auto;
166
170
  bottom: 100%;