@vaadin/grid
Advanced tools
Comparing version 22.0.0-beta2 to 22.0.0-rc1
{ | ||
"name": "@vaadin/grid", | ||
"version": "22.0.0-beta2", | ||
"version": "22.0.0-rc1", | ||
"publishConfig": { | ||
@@ -43,17 +43,17 @@ "access": "public" | ||
"@polymer/polymer": "^3.0.0", | ||
"@vaadin/checkbox": "22.0.0-beta2", | ||
"@vaadin/component-base": "22.0.0-beta2", | ||
"@vaadin/text-field": "22.0.0-beta2", | ||
"@vaadin/vaadin-lumo-styles": "22.0.0-beta2", | ||
"@vaadin/vaadin-material-styles": "22.0.0-beta2", | ||
"@vaadin/vaadin-themable-mixin": "22.0.0-beta2" | ||
"@vaadin/checkbox": "22.0.0-rc1", | ||
"@vaadin/component-base": "22.0.0-rc1", | ||
"@vaadin/text-field": "22.0.0-rc1", | ||
"@vaadin/vaadin-lumo-styles": "22.0.0-rc1", | ||
"@vaadin/vaadin-material-styles": "22.0.0-rc1", | ||
"@vaadin/vaadin-themable-mixin": "22.0.0-rc1" | ||
}, | ||
"devDependencies": { | ||
"@esm-bundle/chai": "^4.3.4", | ||
"@vaadin/polymer-legacy-adapter": "22.0.0-beta2", | ||
"@vaadin/testing-helpers": "^0.3.0", | ||
"@vaadin/polymer-legacy-adapter": "22.0.0-rc1", | ||
"@vaadin/testing-helpers": "^0.3.2", | ||
"lit": "^2.0.0", | ||
"sinon": "^9.2.0" | ||
}, | ||
"gitHead": "f13833683e6667f6ca6678452db14aa6b7eac4a4" | ||
"gitHead": "7b6f44bcd2c0fd415028ace666feeb0fedb1d540" | ||
} |
@@ -100,3 +100,5 @@ /** | ||
get __rowFocusMode() { | ||
return this.__isRow(this._itemsFocusable); | ||
return ( | ||
this.__isRow(this._itemsFocusable) || this.__isRow(this._headerFocusable) || this.__isRow(this._footerFocusable) | ||
); | ||
} | ||
@@ -565,3 +567,6 @@ | ||
while (index >= 0 && index <= tabOrder.length - 1) { | ||
const rowElement = this.__rowFocusMode ? tabOrder[index] : tabOrder[index].parentNode; | ||
let rowElement = tabOrder[index]; | ||
if (rowElement && !this.__rowFocusMode) { | ||
rowElement = tabOrder[index].parentNode; | ||
} | ||
@@ -597,5 +602,5 @@ if (!rowElement || rowElement.hidden) { | ||
const columnIndex = Array.from(targetRow.children).indexOf(this._itemsFocusable); | ||
const focusedItemRow = Array.from(this.$.items.children).filter( | ||
(row) => row.index === this._focusedItemIndex | ||
)[0]; | ||
const focusedItemRow = Array.from(this.$.items.children).find( | ||
(row) => !row.hidden && row.index === this._focusedItemIndex | ||
); | ||
if (focusedItemRow) { | ||
@@ -784,16 +789,24 @@ itemsFocusTarget = focusedItemRow.children[columnIndex]; | ||
_resetKeyboardNavigation() { | ||
if (!this.__isValidFocusable(this._headerFocusable) && this.$.header.firstElementChild) { | ||
this._headerFocusable = Array.from(this.$.header.firstElementChild.children).filter((el) => !el.hidden)[0]; | ||
} | ||
// Header / footer | ||
['header', 'footer'].forEach((section) => { | ||
if (!this.__isValidFocusable(this[`_${section}Focusable`])) { | ||
const firstVisibleRow = [...this.$[section].children].find((row) => row.offsetHeight); | ||
const firstVisibleCell = firstVisibleRow ? [...firstVisibleRow.children].find((cell) => !cell.hidden) : null; | ||
if (firstVisibleRow && firstVisibleCell) { | ||
this[`_${section}Focusable`] = this.__rowFocusMode ? firstVisibleRow : firstVisibleCell; | ||
} | ||
} | ||
}); | ||
// Body | ||
if (!this.__isValidFocusable(this._itemsFocusable) && this.$.items.firstElementChild) { | ||
const firstVisibleIndexRow = this.__getFirstVisibleItem(); | ||
if (firstVisibleIndexRow) { | ||
this._itemsFocusable = Array.from(firstVisibleIndexRow.children).filter((el) => !el.hidden)[0]; | ||
const firstVisibleRow = this.__getFirstVisibleItem(); | ||
const firstVisibleCell = firstVisibleRow ? [...firstVisibleRow.children].find((cell) => !cell.hidden) : null; | ||
if (firstVisibleCell && firstVisibleRow) { | ||
// Reset memoized column | ||
delete this._focusedColumnOrder; | ||
this._itemsFocusable = this.__rowFocusMode ? firstVisibleRow : firstVisibleCell; | ||
} | ||
} | ||
if (!this.__isValidFocusable(this._footerFocusable) && this.$.footer.firstElementChild) { | ||
this._footerFocusable = Array.from(this.$.footer.firstElementChild.children).filter((el) => !el.hidden)[0]; | ||
} | ||
} | ||
@@ -800,0 +813,0 @@ |
@@ -187,3 +187,7 @@ /** | ||
this._grid.selectedItems = selectAll && Array.isArray(this._grid.items) ? this.__getRootLevelItems() : []; | ||
if (selectAll && Array.isArray(this._grid.items)) { | ||
this.__withFilteredItemsArray((items) => (this._grid.selectedItems = items)); | ||
} else { | ||
this._grid.selectedItems = []; | ||
} | ||
} | ||
@@ -255,21 +259,17 @@ | ||
/** @private */ | ||
__getRootLevelItems() { | ||
const rootCache = this._grid._cache; | ||
return [...Array(rootCache.size)].map((_, idx) => rootCache.items[idx]); | ||
} | ||
/** @private */ | ||
__onSelectedItemsChanged() { | ||
this._selectAllChangeLock = true; | ||
if (Array.isArray(this._grid.items)) { | ||
if (!this._grid.selectedItems.length) { | ||
this.selectAll = false; | ||
this.__indeterminate = false; | ||
} else if (this.__arrayContains(this._grid.selectedItems, this.__getRootLevelItems())) { | ||
this.selectAll = true; | ||
this.__indeterminate = false; | ||
} else { | ||
this.selectAll = false; | ||
this.__indeterminate = true; | ||
} | ||
this.__withFilteredItemsArray((items) => { | ||
if (!this._grid.selectedItems.length) { | ||
this.selectAll = false; | ||
this.__indeterminate = false; | ||
} else if (this.__arrayContains(this._grid.selectedItems, items)) { | ||
this.selectAll = true; | ||
this.__indeterminate = false; | ||
} else { | ||
this.selectAll = false; | ||
this.__indeterminate = true; | ||
} | ||
}); | ||
} | ||
@@ -283,2 +283,18 @@ this._selectAllChangeLock = false; | ||
} | ||
/** | ||
* Assuming the grid uses an items array data provider, fetches all the filtered items | ||
* from the data provider and invokes the callback with the resulting array. | ||
* | ||
* @private | ||
*/ | ||
__withFilteredItemsArray(callback) { | ||
const params = { | ||
page: 0, | ||
pageSize: Infinity, | ||
sortOrders: [], | ||
filters: this._grid._mapFilters() | ||
}; | ||
this._grid.dataProvider(params, (items) => callback(items)); | ||
} | ||
} | ||
@@ -285,0 +301,0 @@ |
@@ -10,2 +10,3 @@ /** | ||
import { html, PolymerElement } from '@polymer/polymer/polymer-element.js'; | ||
import { isAndroid, isFirefox, isIOS, isSafari, isTouch } from '@vaadin/component-base/src/browser-utils.js'; | ||
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js'; | ||
@@ -32,11 +33,2 @@ import { processTemplates } from '@vaadin/component-base/src/templates.js'; | ||
const TOUCH_DEVICE = (() => { | ||
try { | ||
document.createEvent('TouchEvent'); | ||
return true; | ||
} catch (e) { | ||
return false; | ||
} | ||
})(); | ||
/** | ||
@@ -331,3 +323,3 @@ * `<vaadin-grid>` is a free, high quality data grid / data table Web Component. The content of the | ||
type: Boolean, | ||
value: /^((?!chrome|android).)*safari/i.test(navigator.userAgent) | ||
value: isSafari | ||
}, | ||
@@ -338,5 +330,3 @@ | ||
type: Boolean, | ||
value: | ||
(/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream) || | ||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1) | ||
value: isIOS | ||
}, | ||
@@ -347,3 +337,3 @@ | ||
type: Boolean, | ||
value: navigator.userAgent.toLowerCase().indexOf('firefox') > -1 | ||
value: isFirefox | ||
}, | ||
@@ -354,3 +344,3 @@ | ||
type: Boolean, | ||
value: /android/i.test(navigator.userAgent) | ||
value: isAndroid | ||
}, | ||
@@ -361,3 +351,3 @@ | ||
type: Boolean, | ||
value: TOUCH_DEVICE | ||
value: isTouch | ||
}, | ||
@@ -522,2 +512,5 @@ | ||
cellCoordinates && cell.parentElement.hidden && this.__focusBodyCell(cellCoordinates); | ||
// Make sure the body has a tabbable element | ||
this._resetKeyboardNavigation(); | ||
} | ||
@@ -543,2 +536,61 @@ } | ||
/** @private */ | ||
__getIntrinsicWidth(col) { | ||
const initialWidth = col.width; | ||
const initialFlexGrow = col.flexGrow; | ||
col.width = 'auto'; | ||
col.flexGrow = 0; | ||
// Note: _allCells only contains cells which are currently rendered in DOM | ||
const width = col._allCells | ||
.filter((cell) => { | ||
// Exclude body cells that are out of the visible viewport | ||
return !this.$.items.contains(cell) || this._isInViewport(cell.parentElement); | ||
}) | ||
.reduce((width, cell) => { | ||
// Add 1px buffer to the offset width to avoid too narrow columns (sub-pixel rendering) | ||
return Math.max(width, cell.offsetWidth + 1); | ||
}, 0); | ||
col.flexGrow = initialFlexGrow; | ||
col.width = initialWidth; | ||
return width; | ||
} | ||
/** @private */ | ||
__getDistributedWidth(col, innerColumn) { | ||
if (col == null || col === this) return 0; | ||
const columnWidth = Math.max(this.__getIntrinsicWidth(col), this.__getDistributedWidth(col.parentElement, col)); | ||
// we're processing a regular grid-column and not a grid-column-group | ||
if (!innerColumn) { | ||
return columnWidth; | ||
} | ||
// At the end, the width of each vaadin-grid-column-group is determined by the sum of the width of its children. | ||
// Here we determine how much space the vaadin-grid-column-group actually needs to render properly and then we distribute that space | ||
// to its children, so when we actually do the summation it will be rendered properly. | ||
// Check out vaadin-grid-column-group:_updateFlexAndWidth | ||
const columnGroup = col; | ||
const columnGroupWidth = columnWidth; | ||
const sumOfWidthOfAllChildColumns = columnGroup._visibleChildColumns | ||
.map((col) => this.__getIntrinsicWidth(col)) | ||
.reduce((sum, curr) => sum + curr, 0); | ||
const extraNecessarySpaceForGridColumnGroup = Math.max(0, columnGroupWidth - sumOfWidthOfAllChildColumns); | ||
// The distribution of the extra necessary space is done according to the intrinsic width of each child column. | ||
// Lets say we need 100 pixels of extra space for the grid-column-group to render properly | ||
// it has two grid-column children, |100px|300px| in total 400px | ||
// the first column gets 25px of the additional space (100/400)*100 = 25 | ||
// the second column gets the 75px of the additional space (300/400)*100 = 75 | ||
const proportionOfExtraSpace = this.__getIntrinsicWidth(innerColumn) / sumOfWidthOfAllChildColumns; | ||
const shareOfInnerColumnFromNecessaryExtraSpace = proportionOfExtraSpace * extraNecessarySpaceForGridColumnGroup; | ||
return this.__getIntrinsicWidth(innerColumn) + shareOfInnerColumnFromNecessaryExtraSpace; | ||
} | ||
/** | ||
@@ -549,34 +601,5 @@ * @param {!Array<!GridColumn>} cols the columns to auto size based on their content width | ||
_recalculateColumnWidths(cols) { | ||
// Note: The `cols.forEach()` loops below could be implemented as a single loop but this has been | ||
// split for performance reasons to batch these similar actions [write/read] together to avoid | ||
// unnecessary layout trashing. | ||
// [write] Set automatic width for all cells (breaks column alignment) | ||
cols.forEach((col) => { | ||
col.width = 'auto'; | ||
col._origFlexGrow = col.flexGrow; | ||
col.flexGrow = 0; | ||
col.width = `${this.__getDistributedWidth(col)}px`; | ||
}); | ||
// [read] Measure max cell width in each column | ||
cols.forEach((col) => { | ||
col._currentWidth = 0; | ||
// Note: _allCells only contains cells which are currently rendered in DOM | ||
col._allCells | ||
.filter((c) => { | ||
// Exclude body cells that are out of the visible viewport | ||
return !this.$.items.contains(c) || this._isInViewport(c.parentElement); | ||
}) | ||
.forEach((c) => { | ||
// Add 1px buffer to the offset width to avoid too narrow columns (sub-pixel rendering) | ||
const cellWidth = c.offsetWidth + 1; | ||
col._currentWidth = Math.max(col._currentWidth, cellWidth); | ||
}); | ||
}); | ||
// [write] Set column widths to fit widest measured content | ||
cols.forEach((col) => { | ||
col.width = `${col._currentWidth}px`; | ||
col.flexGrow = col._origFlexGrow; | ||
col._currentWidth = undefined; | ||
col._origFlexGrow = undefined; | ||
}); | ||
} | ||
@@ -804,2 +827,5 @@ | ||
} | ||
// Make sure the section has a tabbable element | ||
this._resetKeyboardNavigation(); | ||
} | ||
@@ -872,2 +898,3 @@ | ||
this.__updateFooterPositioning(); | ||
this.generateCellClassNames(); | ||
} | ||
@@ -874,0 +901,0 @@ |
@@ -63,2 +63,6 @@ import '@vaadin/vaadin-lumo-styles/color.js'; | ||
[part~='row'] { | ||
position: relative; | ||
} | ||
[part~='row']:focus, | ||
@@ -65,0 +69,0 @@ [part~='cell']:focus { |
@@ -121,2 +121,6 @@ import '@vaadin/vaadin-material-styles/color.js'; | ||
[part~='row'] { | ||
position: relative; | ||
} | ||
[part~='row']:focus, | ||
@@ -123,0 +127,0 @@ [part~='cell']:focus { |
327939
8910
+ Added@vaadin/checkbox@22.0.0-rc1(transitive)
+ Added@vaadin/component-base@22.0.0-rc1(transitive)
+ Added@vaadin/field-base@22.0.0-rc1(transitive)
+ Added@vaadin/icon@22.0.0-rc1(transitive)
+ Added@vaadin/input-container@22.0.0-rc1(transitive)
+ Added@vaadin/text-field@22.0.0-rc1(transitive)
+ Added@vaadin/vaadin-lumo-styles@22.0.0-rc1(transitive)
+ Added@vaadin/vaadin-material-styles@22.0.0-rc1(transitive)
+ Added@vaadin/vaadin-themable-mixin@22.0.0-rc1(transitive)
- Removed@vaadin/checkbox@22.0.0-beta2(transitive)
- Removed@vaadin/component-base@22.0.0-beta2(transitive)
- Removed@vaadin/field-base@22.0.0-beta2(transitive)
- Removed@vaadin/icon@22.0.0-beta2(transitive)
- Removed@vaadin/input-container@22.0.0-beta2(transitive)
- Removed@vaadin/text-field@22.0.0-beta2(transitive)
- Removed@vaadin/vaadin-lumo-styles@22.0.0-beta2(transitive)
- Removed@vaadin/vaadin-material-styles@22.0.0-beta2(transitive)
- Removed@vaadin/vaadin-themable-mixin@22.0.0-beta2(transitive)
Updated@vaadin/checkbox@22.0.0-rc1