@vaadin/vaadin-grid 5.8.3 → 5.9.2

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.3",
18
+ "version": "5.9.2",
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
53
  "scripts": {
56
- "generate-typings": "gen-typescript-declarations --outDir . --verify"
57
- },
58
- "devDependencies": {
59
- "@webcomponents/webcomponentsjs": "^2.0.0",
60
- "wct-browser-legacy": "^1.0.1",
54
+ "generate-typings": "gen-typescript-declarations --outDir . --verify",
55
+ "test": "wct --npm"
56
+ },
57
+ "devDependencies": {
58
+ "@web-padawan/gen-typescript-declarations": "^1.6.2",
59
+ "web-component-tester": "6.9.2",
60
+ "@polymer/app-localize-behavior": "^3.0.0",
61
+ "@polymer/iron-ajax": "^3.0.0",
62
+ "@polymer/iron-component-page": "^4.0.0",
63
+ "@polymer/iron-image": "^3.0.0",
64
+ "@polymer/iron-list": "^3.0.0",
65
+ "@polymer/iron-media-query": "^3.0.0",
61
66
  "@polymer/iron-test-helpers": "^3.0.0",
62
- "@polymer/paper-input": "^3.0.0",
63
67
  "@polymer/paper-checkbox": "^3.0.0",
64
- "@polymer/iron-flex-layout": "^3.0.0",
65
- "@polymer/iron-image": "^3.0.0",
68
+ "@polymer/paper-input": "^3.0.0",
66
69
  "@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",
70
+ "@polymer/test-fixture": "^4.0.0",
73
71
  "@vaadin/vaadin-button": "^2.4.0",
74
- "@vaadin/vaadin-context-menu": "^4.5.0"
72
+ "@vaadin/vaadin-context-menu": "^4.5.0",
73
+ "@vaadin/vaadin-demo-helpers": "^3.1.0",
74
+ "@webcomponents/webcomponentsjs": "^2.0.0",
75
+ "wct-browser-legacy": "^1.0.1"
75
76
  }
76
77
  }
@@ -8,6 +8,7 @@ import '@polymer/polymer/polymer-legacy.js';
8
8
  import { microTask } from '@polymer/polymer/lib/utils/async.js';
9
9
  import { FlattenedNodesObserver } from '@polymer/polymer/lib/utils/flattened-nodes-observer.js';
10
10
  import { ColumnBaseMixin } from './vaadin-grid-column.js';
11
+ import { GridHelper } from './vaadin-grid-helpers.js';
11
12
  import { PolymerElement } from '@polymer/polymer/polymer-element.js';
12
13
  /**
13
14
  * A `<vaadin-grid-column-group>` is used to make groups of columns in `<vaadin-grid>` and
@@ -153,7 +154,7 @@ class GridColumnGroupElement extends ColumnBaseMixin(PolymerElement) {
153
154
 
154
155
  // In an unlikely situation where a group has more than 9 child columns,
155
156
  // the child scope must have 1 digit less...
156
- const childCountDigits = ~~(Math.log(rootColumns.length) / Math.log(Math.LN10)) + 1;
157
+ const childCountDigits = ~~(Math.log(rootColumns.length) / Math.LN10) + 1;
157
158
 
158
159
  // Final scope for the child columns needs to mind both factors.
159
160
  const scope = Math.pow(10, trailingZeros - childCountDigits);
@@ -163,7 +164,7 @@ class GridColumnGroupElement extends ColumnBaseMixin(PolymerElement) {
163
164
  _rootColumns.sort((a, b) => a._order - b._order);
164
165
  }
165
166
 
166
- _rootColumns.forEach((column, index) => column._order = order + ((index + 1) * scope));
167
+ GridHelper._updateColumnOrders(_rootColumns, scope, order);
167
168
  }
168
169
  }
169
170
 
@@ -5,9 +5,9 @@ This program is available under Apache License Version 2.0, available at https:/
5
5
  */
6
6
  import { GestureEventListeners } from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
7
7
 
8
+ import { GridHelper } from './vaadin-grid-helpers.js';
8
9
  import { addListener } from '@polymer/polymer/lib/utils/gestures.js';
9
10
  import { dom } from '@polymer/polymer/lib/legacy/polymer.dom.js';
10
- import { useShadow } from '@polymer/polymer/lib/utils/settings.js';
11
11
 
12
12
  /**
13
13
  * @polymerMixin
@@ -213,15 +213,24 @@ export const ColumnReorderingMixin = superClass => class ColumnReorderingMixin e
213
213
  if (!this._draggedColumn) {
214
214
  this._toggleAttribute('no-content-pointer-events', true, this.$.scroller);
215
215
  }
216
+ // Workaround a ShadyDOM bug
217
+ this._reorderGhost.hidden = true;
218
+
216
219
  let cell;
217
- if (useShadow) {
220
+ if (this.shadowRoot.elementFromPoint) {
218
221
  cell = this.shadowRoot.elementFromPoint(x, y);
219
222
  } else {
220
223
  cell = document.elementFromPoint(x, y);
224
+ }
221
225
 
222
- // Workaround a FF58 bug
226
+ this._reorderGhost.hidden = false;
227
+
228
+ // Workaround FF58/ShadyDOM bugs
229
+ while (!cell._column && cell.parentElement) {
223
230
  if (cell.localName === 'vaadin-grid-cell-content') {
224
231
  cell = cell.assignedSlot.parentNode;
232
+ } else {
233
+ cell = cell.parentElement;
225
234
  }
226
235
 
227
236
  }
@@ -293,7 +302,7 @@ export const ColumnReorderingMixin = superClass => class ColumnReorderingMixin e
293
302
  // Reset all column orders
294
303
  columnTree[0].forEach((column, index) => column._order = 0);
295
304
  // Set order numbers to top-level columns
296
- columnTree[0].forEach((column, index) => column._order = (index + 1) * this._orderBaseScope);
305
+ GridHelper._updateColumnOrders(columnTree[0], this._orderBaseScope, 0);
297
306
  }
298
307
 
299
308
  /**
@@ -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;
@@ -395,7 +395,7 @@ export const DataProviderMixin = superClass => class DataProviderMixin extends s
395
395
  this._debouncerApplyCachedData.flush();
396
396
  }
397
397
 
398
- this.__itemsReceived();
398
+ this.__flushPendingRecalculateColumnWidths();
399
399
  });
400
400
  }
401
401
  }
@@ -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]
@@ -0,0 +1,26 @@
1
+ /**
2
+ @license
3
+ Copyright (c) 2017 Vaadin Ltd.
4
+ This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ /** @private */
7
+ export const GridHelper = class VaadinGridHelper {
8
+
9
+ /**
10
+ * @param {Array<Object>} columns array of columns to be modified
11
+ * @param {number} scope multiplier added to base order for each column
12
+ * @param {number} baseOrder base number used for order
13
+ */
14
+ static _updateColumnOrders(columns, scope, baseOrder) {
15
+ let c = 1;
16
+ columns.forEach((column) => {
17
+ // avoid multiples of 10 because they introduce and extra zero and
18
+ // causes the underlying calculations for child order goes wrong
19
+ if (c % 10 === 0) {
20
+ c++;
21
+ }
22
+ column._order = baseOrder + c * scope;
23
+ c++;
24
+ });
25
+ }
26
+ };
@@ -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);
@@ -209,6 +215,7 @@ class GridScrollerElement extends PolymerIronList {
209
215
  // Ensure the rows are in order after increasing pool
210
216
  this.__reorderChildNodes();
211
217
  }
218
+ this.__flushPendingRecalculateColumnWidths();
212
219
  });
213
220
  }
214
221
  }
@@ -255,6 +262,10 @@ class GridScrollerElement extends PolymerIronList {
255
262
  * @protected
256
263
  */
257
264
  _assignModels(itemSet) {
265
+ // Skip here if internal flag for preventing item updates is set
266
+ if (this._preventItemUpdates) {
267
+ return;
268
+ }
258
269
  this._iterateItems((pidx, vidx) => {
259
270
  const el = this._physicalItems[pidx];
260
271
  this._toggleAttribute('hidden', vidx >= this._effectiveSize, el);
@@ -430,6 +441,19 @@ class GridScrollerElement extends PolymerIronList {
430
441
  super._resizeHandler();
431
442
  flush();
432
443
  }
444
+
445
+ __isCreatingRows() {
446
+ // iron-list's _increasePoolIfNeeded function may have scheduled a debouncer
447
+ // that will re-invoke _increasePoolIfNeeded (in vaadin-grid-scroller)
448
+ const schedulingDebounceIncreasePool = this._debouncers
449
+ && this._debouncers._increasePoolIfNeeded
450
+ && this._debouncers._increasePoolIfNeeded.isActive();
451
+ // vaadin-grid-scroller's overridden _increasePoolIfNeeded may have scheduled a _debounceIncreasePool debouncer
452
+ const debouncingIncreasePoolActive = this._debounceIncreasePool && this._debounceIncreasePool.isActive();
453
+
454
+ // If either of the conditions are true, we consider the grid is still in the process of creating new rows
455
+ return schedulingDebounceIncreasePool || debouncingIncreasePoolActive;
456
+ }
433
457
  }
434
458
 
435
459
  customElements.define(GridScrollerElement.is, GridScrollerElement);
@@ -197,7 +197,7 @@ class GridTreeToggleElement extends ThemableMixin(DirMixin(PolymerElement)) {
197
197
  /** @private */
198
198
  _levelChanged(level) {
199
199
  const value = Number(level).toString();
200
- this.style['---level'] = value;
200
+ this.updateStyles({'---level': value});
201
201
  // Async is to make DOM updates applied before evaluating the style
202
202
  // update, required for polyfilled RTL support in MSIE and Edge.
203
203
  this._debouncerUpdateLevel = Debouncer.debounce(
@@ -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
@@ -313,7 +314,7 @@ declare class GridElement extends
313
314
  allRowsVisible: boolean;
314
315
  connectedCallback(): void;
315
316
  attributeChangedCallback(name: string, oldValue: string|null, newValue: string|null): void;
316
- __itemsReceived(): void;
317
+ __flushPendingRecalculateColumnWidths(): void;
317
318
 
318
319
  /**
319
320
  * Updates the `width` of all columns which have `autoWidth` set to `true`.
@@ -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.2';
326
+ return '5.9.2';
326
327
  }
327
328
 
328
329
  static get observers() {
@@ -451,46 +452,80 @@ class GridElement extends
451
452
  }
452
453
 
453
454
  /** @protected */
454
- __itemsReceived() {
455
+ __flushPendingRecalculateColumnWidths() {
455
456
  if (this._recalculateColumnWidthOnceLoadingFinished
456
- && !this._cache.isLoading()
457
- && this.__hasRowsWithClientHeight()) {
457
+ && !this._cache.isLoading()
458
+ && this.__hasRowsWithClientHeight()
459
+ && !this.__isCreatingRows()) {
458
460
  this._recalculateColumnWidthOnceLoadingFinished = false;
459
461
  this.recalculateColumnWidths();
460
462
  }
461
463
  }
462
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
+
463
522
  /**
464
523
  * @param {!Array<!GridColumnElement>} cols the columns to auto size based on their content width
465
524
  * @private
466
525
  */
467
526
  _recalculateColumnWidths(cols) {
468
- // Note: The `cols.forEach()` loops below could be implemented as a single loop but this has been
469
- // split for performance reasons to batch these similar actions [write/read] together to avoid
470
- // unnecessary layout trashing.
471
-
472
- // [write] Set automatic width for all cells (breaks column alignment)
473
- cols.forEach(col => {
474
- col.width = 'auto';
475
- col._origFlexGrow = col.flexGrow;
476
- col.flexGrow = 0;
477
- });
478
- // [read] Measure max cell width in each column
479
- cols.forEach(col => {
480
- col._currentWidth = 0;
481
- // Note: _allCells only contains cells which are currently rendered in DOM
482
- col._allCells.forEach(c => {
483
- // Add 1px buffer to the offset width to avoid too narrow columns (sub-pixel rendering)
484
- const cellWidth = c.offsetWidth + 1;
485
- col._currentWidth = Math.max(col._currentWidth, cellWidth);
486
- });
487
- });
488
- // [write] Set column widths to fit widest measured content
489
- cols.forEach(col => {
490
- col.width = `${col._currentWidth}px`;
491
- col.flexGrow = col._origFlexGrow;
492
- col._currentWidth = undefined;
493
- col._origFlexGrow = undefined;
527
+ cols.forEach((col) => {
528
+ col.width = `${this.__getDistributedWidth(col)}px`;
494
529
  });
495
530
  }
496
531
 
@@ -501,7 +536,7 @@ class GridElement extends
501
536
  if (!this._columnTree) {
502
537
  return; // No columns
503
538
  }
504
- if (this._cache.isLoading()) {
539
+ if (this._cache.isLoading() || this.__isCreatingRows()) {
505
540
  this._recalculateColumnWidthOnceLoadingFinished = true;
506
541
  } else {
507
542
  const cols = this._getColumns().filter(col => !col.hidden && col.autoWidth);
@@ -730,6 +765,7 @@ class GridElement extends
730
765
  }
731
766
 
732
767
  this._toggleAttribute('first', index === 0, row);
768
+ this._toggleAttribute('last', index === this._effectiveSize - 1, row);
733
769
  this._toggleAttribute('odd', index % 2, row);
734
770
  this._a11yUpdateRowRowindex(row, index);
735
771
  this._getItem(index, row);
@@ -862,7 +898,7 @@ class GridElement extends
862
898
  this._render();
863
899
  e.stopPropagation();
864
900
  this.notifyResize();
865
- this.__itemsReceived();
901
+ this.__flushPendingRecalculateColumnWidths();
866
902
 
867
903
  requestAnimationFrame(() => {
868
904
  this.__scrollToPendingIndex();
@@ -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%;