@vaadin/grid 23.3.3 → 24.0.0-alpha10

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 (60) hide show
  1. package/package.json +10 -10
  2. package/src/all-imports.js +1 -1
  3. package/src/array-data-provider.js +1 -1
  4. package/src/lit/column-renderer-directives.d.ts +1 -1
  5. package/src/lit/column-renderer-directives.js +1 -1
  6. package/src/lit/renderer-directives.d.ts +1 -1
  7. package/src/lit/renderer-directives.js +1 -1
  8. package/src/vaadin-grid-a11y-mixin.js +12 -9
  9. package/src/vaadin-grid-active-item-mixin.d.ts +1 -1
  10. package/src/vaadin-grid-active-item-mixin.js +5 -3
  11. package/src/vaadin-grid-array-data-provider-mixin.d.ts +1 -1
  12. package/src/vaadin-grid-array-data-provider-mixin.js +1 -1
  13. package/src/vaadin-grid-column-group.d.ts +1 -1
  14. package/src/vaadin-grid-column-group.js +17 -17
  15. package/src/vaadin-grid-column-reordering-mixin.d.ts +1 -1
  16. package/src/vaadin-grid-column-reordering-mixin.js +7 -9
  17. package/src/vaadin-grid-column-resizing-mixin.js +6 -5
  18. package/src/vaadin-grid-column.d.ts +1 -1
  19. package/src/vaadin-grid-column.js +48 -34
  20. package/src/vaadin-grid-data-provider-mixin.d.ts +1 -1
  21. package/src/vaadin-grid-data-provider-mixin.js +33 -7
  22. package/src/vaadin-grid-drag-and-drop-mixin.d.ts +1 -1
  23. package/src/vaadin-grid-drag-and-drop-mixin.js +23 -18
  24. package/src/vaadin-grid-dynamic-columns-mixin.js +5 -4
  25. package/src/vaadin-grid-event-context-mixin.d.ts +1 -1
  26. package/src/vaadin-grid-event-context-mixin.js +1 -1
  27. package/src/vaadin-grid-filter-column.d.ts +1 -1
  28. package/src/vaadin-grid-filter-column.js +1 -2
  29. package/src/vaadin-grid-filter-mixin.js +1 -1
  30. package/src/vaadin-grid-filter.d.ts +3 -2
  31. package/src/vaadin-grid-filter.js +27 -22
  32. package/src/vaadin-grid-helpers.js +104 -1
  33. package/src/vaadin-grid-keyboard-navigation-mixin.js +35 -34
  34. package/src/vaadin-grid-row-details-mixin.d.ts +1 -1
  35. package/src/vaadin-grid-row-details-mixin.js +5 -4
  36. package/src/vaadin-grid-scroll-mixin.d.ts +1 -1
  37. package/src/vaadin-grid-scroll-mixin.js +10 -9
  38. package/src/vaadin-grid-selection-column.d.ts +1 -1
  39. package/src/vaadin-grid-selection-column.js +1 -1
  40. package/src/vaadin-grid-selection-mixin.d.ts +1 -1
  41. package/src/vaadin-grid-selection-mixin.js +1 -1
  42. package/src/vaadin-grid-sort-column.d.ts +1 -1
  43. package/src/vaadin-grid-sort-column.js +1 -1
  44. package/src/vaadin-grid-sort-mixin.d.ts +1 -1
  45. package/src/vaadin-grid-sort-mixin.js +1 -1
  46. package/src/vaadin-grid-sorter.d.ts +1 -1
  47. package/src/vaadin-grid-sorter.js +1 -1
  48. package/src/vaadin-grid-styles.js +1 -1
  49. package/src/vaadin-grid-styling-mixin.d.ts +38 -2
  50. package/src/vaadin-grid-styling-mixin.js +77 -6
  51. package/src/vaadin-grid-tree-column.d.ts +1 -8
  52. package/src/vaadin-grid-tree-column.js +2 -25
  53. package/src/vaadin-grid-tree-toggle.d.ts +1 -1
  54. package/src/vaadin-grid-tree-toggle.js +1 -1
  55. package/src/vaadin-grid.d.ts +57 -25
  56. package/src/vaadin-grid.js +131 -79
  57. package/theme/lumo/vaadin-grid-styles.js +14 -14
  58. package/theme/material/vaadin-grid-styles.js +1 -1
  59. package/web-types.json +15 -26
  60. package/web-types.lit.json +11 -11
@@ -1,8 +1,10 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2016 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
+ import { iterateChildren, updateRowStates } from './vaadin-grid-helpers.js';
7
+
6
8
  const DropMode = {
7
9
  BETWEEN: 'between',
8
10
  ON_TOP: 'on-top',
@@ -126,7 +128,7 @@ export const DragAndDropMixin = (superClass) =>
126
128
  // Safari doesn't position drag images from transformed
127
129
  // elements properly so we need to switch to use top temporarily
128
130
  const transform = row.style.transform;
129
- row.style.top = /translateY\((.*)\)/.exec(transform)[1];
131
+ row.style.top = /translateY\((.*)\)/u.exec(transform)[1];
130
132
  row.style.transform = 'none';
131
133
  requestAnimationFrame(() => {
132
134
  row.style.top = '';
@@ -154,13 +156,14 @@ export const DragAndDropMixin = (superClass) =>
154
156
  // Set the default transfer data
155
157
  e.dataTransfer.setData('text', this.__formatDefaultTransferData(rows));
156
158
 
157
- row.setAttribute('dragstart', rows.length > 1 ? rows.length : '');
159
+ updateRowStates(row, { dragstart: rows.length > 1 ? `${rows.length}` : '' });
158
160
  this.style.setProperty('--_grid-drag-start-x', `${e.clientX - rowRect.left + 20}px`);
159
161
  this.style.setProperty('--_grid-drag-start-y', `${e.clientY - rowRect.top + 10}px`);
160
162
 
161
163
  requestAnimationFrame(() => {
162
- row.removeAttribute('dragstart');
163
- this.updateStyles({ '--_grid-drag-start-x': '', '--_grid-drag-start-y': '' });
164
+ updateRowStates(row, { dragstart: null });
165
+ this.style.setProperty('--_grid-drag-start-x', '');
166
+ this.style.setProperty('--_grid-drag-start-y', '');
164
167
  });
165
168
 
166
169
  const event = new CustomEvent('grid-dragstart', {
@@ -252,7 +255,7 @@ export const DragAndDropMixin = (superClass) =>
252
255
  } else if (row) {
253
256
  this._dragOverItem = row._item;
254
257
  if (row.getAttribute('dragover') !== this._dropLocation) {
255
- row.setAttribute('dragover', this._dropLocation);
258
+ updateRowStates(row, { dragover: this._dropLocation }, true);
256
259
  }
257
260
  } else {
258
261
  this._clearDragStyles();
@@ -306,7 +309,9 @@ export const DragAndDropMixin = (superClass) =>
306
309
  /** @protected */
307
310
  _clearDragStyles() {
308
311
  this.removeAttribute('dragover');
309
- Array.from(this.$.items.children).forEach((row) => row.removeAttribute('dragover'));
312
+ iterateChildren(this.$.items, (row) => {
313
+ updateRowStates(row, { dragover: null }, true);
314
+ });
310
315
  }
311
316
 
312
317
  /** @private */
@@ -368,11 +373,11 @@ export const DragAndDropMixin = (superClass) =>
368
373
  * the conditions change.
369
374
  */
370
375
  filterDragAndDrop() {
371
- Array.from(this.$.items.children)
372
- .filter((row) => !row.hidden)
373
- .forEach((row) => {
376
+ iterateChildren(this.$.items, (row) => {
377
+ if (!row.hidden) {
374
378
  this._filterDragAndDrop(row, this.__getRowModel(row));
375
- });
379
+ }
380
+ });
376
381
  }
377
382
 
378
383
  /**
@@ -385,18 +390,18 @@ export const DragAndDropMixin = (superClass) =>
385
390
  const dragDisabled = !this.rowsDraggable || loading || (this.dragFilter && !this.dragFilter(model));
386
391
  const dropDisabled = !this.dropMode || loading || (this.dropFilter && !this.dropFilter(model));
387
392
 
388
- const draggableElements = Array.from(row.children).map((cell) => cell._content);
389
-
390
- draggableElements.forEach((e) => {
393
+ iterateChildren(row, (cell) => {
391
394
  if (dragDisabled) {
392
- e.removeAttribute('draggable');
395
+ cell._content.removeAttribute('draggable');
393
396
  } else {
394
- e.setAttribute('draggable', true);
397
+ cell._content.setAttribute('draggable', true);
395
398
  }
396
399
  });
397
400
 
398
- row.toggleAttribute('drag-disabled', !!dragDisabled);
399
- row.toggleAttribute('drop-disabled', !!dropDisabled);
401
+ updateRowStates(row, {
402
+ 'drag-disabled': !!dragDisabled,
403
+ 'drop-disabled': !!dropDisabled,
404
+ });
400
405
  }
401
406
 
402
407
  /**
@@ -1,12 +1,13 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2016 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { FlattenedNodesObserver } from '@polymer/polymer/lib/utils/flattened-nodes-observer.js';
7
7
  import { PolymerElement } from '@polymer/polymer/polymer-element.js';
8
8
  import { timeOut } from '@vaadin/component-base/src/async.js';
9
9
  import { Debouncer } from '@vaadin/component-base/src/debounce.js';
10
+ import { updateCellState } from './vaadin-grid-helpers.js';
10
11
 
11
12
  function arrayEquals(arr1, arr2) {
12
13
  if (!arr1 || !arr2 || arr1.length !== arr2.length) {
@@ -160,8 +161,8 @@ export const DynamicColumnsMixin = (superClass) =>
160
161
  return a._column._order - b._column._order;
161
162
  })
162
163
  .forEach((cell, cellIndex, children) => {
163
- cell.toggleAttribute('first-column', cellIndex === 0);
164
- cell.toggleAttribute('last-column', cellIndex === children.length - 1);
164
+ updateCellState(cell, 'first-column', cellIndex === 0);
165
+ updateCellState(cell, 'last-column', cellIndex === children.length - 1);
165
166
  });
166
167
  }
167
168
 
@@ -171,6 +172,6 @@ export const DynamicColumnsMixin = (superClass) =>
171
172
  * @protected
172
173
  */
173
174
  _isColumnElement(node) {
174
- return node.nodeType === Node.ELEMENT_NODE && /\bcolumn\b/.test(node.localName);
175
+ return node.nodeType === Node.ELEMENT_NODE && /\bcolumn\b/u.test(node.localName);
175
176
  }
176
177
  };
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2016 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import type { Constructor } from '@open-wc/dedupe-mixin';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2016 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2016 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import type { GridDefaultItem } from './vaadin-grid.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2016 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import './vaadin-grid-filter.js';
@@ -60,7 +60,6 @@ class GridFilterColumn extends GridColumn {
60
60
  if (!filter) {
61
61
  filter = document.createElement('vaadin-grid-filter');
62
62
  textField = document.createElement('vaadin-text-field');
63
- textField.setAttribute('slot', 'filter');
64
63
  textField.setAttribute('theme', 'small');
65
64
  textField.setAttribute('style', 'max-width: 100%;');
66
65
  textField.setAttribute('focus-target', '');
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2016 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
 
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2016 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
+ import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
6
7
 
7
8
  /**
8
9
  * Fired when the `value` property changes.
@@ -40,7 +41,7 @@ export interface GridFilterEventMap extends HTMLElementEventMap, GridFilterCusto
40
41
  *
41
42
  * @fires {CustomEvent} value-changed - Fired when the `value` property changes.
42
43
  */
43
- declare class GridFilter extends HTMLElement {
44
+ declare class GridFilter extends ControllerMixin(HTMLElement) {
44
45
  /**
45
46
  * JS Path of the property in the item used for filtering the data.
46
47
  */
@@ -1,12 +1,14 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2016 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import '@vaadin/text-field/src/vaadin-text-field.js';
7
7
  import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
8
8
  import { timeOut } from '@vaadin/component-base/src/async.js';
9
+ import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
9
10
  import { Debouncer } from '@vaadin/component-base/src/debounce.js';
11
+ import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
10
12
 
11
13
  /**
12
14
  * `<vaadin-grid-filter>` is a helper element for the `<vaadin-grid>` that provides out-of-the-box UI controls,
@@ -35,7 +37,7 @@ import { Debouncer } from '@vaadin/component-base/src/debounce.js';
35
37
  *
36
38
  * @extends HTMLElement
37
39
  */
38
- class GridFilter extends class extends PolymerElement {} {
40
+ class GridFilter extends ControllerMixin(PolymerElement) {
39
41
  static get template() {
40
42
  return html`
41
43
  <style>
@@ -44,14 +46,12 @@ class GridFilter extends class extends PolymerElement {} {
44
46
  max-width: 100%;
45
47
  }
46
48
 
47
- #filter {
49
+ ::slotted(*) {
48
50
  width: 100%;
49
51
  box-sizing: border-box;
50
52
  }
51
53
  </style>
52
- <slot name="filter">
53
- <vaadin-text-field id="filter" value="{{value}}"></vaadin-text-field>
54
- </slot>
54
+ <slot></slot>
55
55
  `;
56
56
  }
57
57
 
@@ -75,39 +75,42 @@ class GridFilter extends class extends PolymerElement {} {
75
75
  },
76
76
 
77
77
  /** @private */
78
- _connected: Boolean,
78
+ _textField: {
79
+ type: Object,
80
+ },
79
81
  };
80
82
  }
81
83
 
82
- /** @protected */
83
- connectedCallback() {
84
- super.connectedCallback();
85
- this._connected = true;
86
- }
87
-
88
84
  static get observers() {
89
- return ['_filterChanged(path, value, _connected)'];
85
+ return ['_filterChanged(path, value, _textField)'];
90
86
  }
91
87
 
92
88
  /** @protected */
93
89
  ready() {
94
90
  super.ready();
95
91
 
96
- const child = this.firstElementChild;
97
- if (child && child.getAttribute('slot') !== 'filter') {
98
- console.warn('Make sure you have assigned slot="filter" to the child elements of <vaadin-grid-filter>');
99
- child.setAttribute('slot', 'filter');
100
- }
92
+ this._filterController = new SlotController(this, '', 'vaadin-text-field', {
93
+ initializer: (field) => {
94
+ field.addEventListener('value-changed', (e) => {
95
+ this.value = e.detail.value;
96
+ });
97
+
98
+ this._textField = field;
99
+ },
100
+ });
101
+ this.addController(this._filterController);
101
102
  }
102
103
 
103
104
  /** @private */
104
- _filterChanged(path, value, connected) {
105
- if (path === undefined || value === undefined || !connected) {
105
+ _filterChanged(path, value, textField) {
106
+ if (path === undefined || value === undefined || !textField) {
106
107
  return;
107
108
  }
108
109
  if (this._previousValue === undefined && value === '') {
109
110
  return;
110
111
  }
112
+
113
+ textField.value = value;
111
114
  this._previousValue = value;
112
115
 
113
116
  this._debouncerFilterChanged = Debouncer.debounce(this._debouncerFilterChanged, timeOut.after(200), () => {
@@ -116,7 +119,9 @@ class GridFilter extends class extends PolymerElement {} {
116
119
  }
117
120
 
118
121
  focus() {
119
- this.$.filter.focus();
122
+ if (this._textField) {
123
+ this._textField.focus();
124
+ }
120
125
  }
121
126
  }
122
127
 
@@ -1,8 +1,25 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2016 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
+ import { addValueToAttribute, removeValueFromAttribute } from '@vaadin/component-base/src/dom-utils.js';
7
+
8
+ /**
9
+ * @param {HTMLTableRowElement} row the table row
10
+ * @return {HTMLTableCellElement[]} array of cells
11
+ */
12
+ export function getBodyRowCells(row) {
13
+ return Array.from(row.querySelectorAll('[part~="cell"]:not([part~="details-cell"])'));
14
+ }
15
+
16
+ /**
17
+ * @param {HTMLElement} container the DOM element with children
18
+ * @param {Function} callback function to call on each child
19
+ */
20
+ export function iterateChildren(container, callback) {
21
+ [...container.children].forEach(callback);
22
+ }
6
23
 
7
24
  /**
8
25
  * @param {Array<Object>} columns array of columns to be modified
@@ -21,3 +38,89 @@ export function updateColumnOrders(columns, scope, baseOrder) {
21
38
  c += 1;
22
39
  });
23
40
  }
41
+
42
+ /**
43
+ * @param {!HTMLElement} element
44
+ * @param {string} attribute
45
+ * @param {boolean | string | null | undefined} value
46
+ */
47
+ export function updateState(element, attribute, value) {
48
+ switch (typeof value) {
49
+ case 'boolean':
50
+ element.toggleAttribute(attribute, value);
51
+ break;
52
+ case 'string':
53
+ element.setAttribute(attribute, value);
54
+ break;
55
+ default:
56
+ // Value set to null / undefined
57
+ element.removeAttribute(attribute);
58
+ break;
59
+ }
60
+ }
61
+
62
+ /**
63
+ * @param {!HTMLElement} element
64
+ * @param {boolean | string | null | undefined} value
65
+ * @param {string} part
66
+ */
67
+ export function updatePart(element, value, part) {
68
+ if (value || value === '') {
69
+ addValueToAttribute(element, 'part', part);
70
+ } else {
71
+ removeValueFromAttribute(element, 'part', part);
72
+ }
73
+ }
74
+
75
+ /**
76
+ * @param {HTMLTableCellElement[]} cells
77
+ * @param {string} part
78
+ * @param {boolean | string | null | undefined} value
79
+ */
80
+ export function updateCellsPart(cells, part, value) {
81
+ cells.forEach((cell) => {
82
+ updatePart(cell, value, part);
83
+ });
84
+ }
85
+
86
+ /**
87
+ * @param {!HTMLElement} row
88
+ * @param {Object} states
89
+ * @param {boolean} appendValue
90
+ */
91
+ export function updateRowStates(row, states, appendValue) {
92
+ const cells = getBodyRowCells(row);
93
+
94
+ Object.entries(states).forEach(([state, value]) => {
95
+ // Row state attribute
96
+ updateState(row, state, value);
97
+
98
+ const rowPart = appendValue ? `${state}-${value}-row` : `${state}-row`;
99
+
100
+ // Row part attribute
101
+ updatePart(row, value, rowPart);
102
+
103
+ // Cells part attribute
104
+ updateCellsPart(cells, `${rowPart}-cell`, value);
105
+ });
106
+ }
107
+
108
+ /**
109
+ * @param {!HTMLElement} cell
110
+ * @param {string} attribute
111
+ * @param {boolean | string | null | undefined} value
112
+ * @param {string} part
113
+ * @param {?string} oldPart
114
+ */
115
+ export function updateCellState(cell, attribute, value, part, oldPart) {
116
+ // Toggle state attribute on the cell
117
+ updateState(cell, attribute, value);
118
+
119
+ // Remove old part from the attribute
120
+ if (oldPart) {
121
+ updatePart(cell, false, oldPart);
122
+ }
123
+
124
+ // Add new part to the cell attribute
125
+ updatePart(cell, value, part || `${attribute}-cell`);
126
+ }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2016 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { addValueToAttribute, removeValueFromAttribute } from '@vaadin/component-base/src/dom-utils.js';
@@ -77,6 +77,33 @@ export const KeyboardNavigationMixin = (superClass) =>
77
77
  };
78
78
  }
79
79
 
80
+ /** @private */
81
+ get __rowFocusMode() {
82
+ return (
83
+ this.__isRow(this._itemsFocusable) || this.__isRow(this._headerFocusable) || this.__isRow(this._footerFocusable)
84
+ );
85
+ }
86
+
87
+ set __rowFocusMode(value) {
88
+ ['_itemsFocusable', '_footerFocusable', '_headerFocusable'].forEach((prop) => {
89
+ const focusable = this[prop];
90
+ if (value) {
91
+ const parent = focusable && focusable.parentElement;
92
+ if (this.__isCell(focusable)) {
93
+ // Cell itself focusable (default)
94
+ this[prop] = parent;
95
+ } else if (this.__isCell(parent)) {
96
+ // Focus button mode is enabled for the column,
97
+ // button element inside the cell is focusable.
98
+ this[prop] = parent.parentElement;
99
+ }
100
+ } else if (!value && this.__isRow(focusable)) {
101
+ const cell = focusable.firstElementChild;
102
+ this[prop] = cell._focusButton || cell;
103
+ }
104
+ });
105
+ }
106
+
80
107
  /** @protected */
81
108
  ready() {
82
109
  super.ready();
@@ -108,33 +135,6 @@ export const KeyboardNavigationMixin = (superClass) =>
108
135
  });
109
136
  }
110
137
 
111
- /** @private */
112
- get __rowFocusMode() {
113
- return (
114
- this.__isRow(this._itemsFocusable) || this.__isRow(this._headerFocusable) || this.__isRow(this._footerFocusable)
115
- );
116
- }
117
-
118
- set __rowFocusMode(value) {
119
- ['_itemsFocusable', '_footerFocusable', '_headerFocusable'].forEach((prop) => {
120
- const focusable = this[prop];
121
- if (value) {
122
- const parent = focusable && focusable.parentElement;
123
- if (this.__isCell(focusable)) {
124
- // Cell itself focusable (default)
125
- this[prop] = parent;
126
- } else if (this.__isCell(parent)) {
127
- // Focus button mode is enabled for the column,
128
- // button element inside the cell is focusable.
129
- this[prop] = parent.parentElement;
130
- }
131
- } else if (!value && this.__isRow(focusable)) {
132
- const cell = focusable.firstElementChild;
133
- this[prop] = cell._focusButton || cell;
134
- }
135
- });
136
- }
137
-
138
138
  /** @private */
139
139
  _focusableChanged(focusable, oldFocusable) {
140
140
  if (oldFocusable) {
@@ -300,6 +300,7 @@ export const KeyboardNavigationMixin = (superClass) =>
300
300
  e.preventDefault();
301
301
 
302
302
  const visibleItemsCount = this._lastVisibleIndex - this._firstVisibleIndex - 1;
303
+ const isRTL = this.__isRTL;
303
304
 
304
305
  // Handle keyboard interaction as defined in:
305
306
  // https://w3c.github.io/aria-practices/#keyboard-interaction-24
@@ -308,10 +309,10 @@ export const KeyboardNavigationMixin = (superClass) =>
308
309
  dy = 0;
309
310
  switch (key) {
310
311
  case 'ArrowRight':
311
- dx = this.__isRTL ? -1 : 1;
312
+ dx = isRTL ? -1 : 1;
312
313
  break;
313
314
  case 'ArrowLeft':
314
- dx = this.__isRTL ? 1 : -1;
315
+ dx = isRTL ? 1 : -1;
315
316
  break;
316
317
  case 'Home':
317
318
  if (this.__rowFocusMode) {
@@ -361,8 +362,8 @@ export const KeyboardNavigationMixin = (superClass) =>
361
362
  return;
362
363
  }
363
364
 
364
- const forwardsKey = this.__isRTL ? 'ArrowLeft' : 'ArrowRight';
365
- const backwardsKey = this.__isRTL ? 'ArrowRight' : 'ArrowLeft';
365
+ const forwardsKey = isRTL ? 'ArrowLeft' : 'ArrowRight';
366
+ const backwardsKey = isRTL ? 'ArrowRight' : 'ArrowLeft';
366
367
  if (key === forwardsKey) {
367
368
  // "Right Arrow:"
368
369
  if (this.__rowFocusMode) {
@@ -585,7 +586,7 @@ export const KeyboardNavigationMixin = (superClass) =>
585
586
  const localTarget = e.composedPath()[0];
586
587
  const localTargetIsTextInput =
587
588
  localTarget.localName === 'input' &&
588
- !/^(button|checkbox|color|file|image|radio|range|reset|submit)$/i.test(localTarget.type);
589
+ !/^(button|checkbox|color|file|image|radio|range|reset|submit)$/iu.test(localTarget.type);
589
590
 
590
591
  let wantInteracting;
591
592
  switch (key) {
@@ -723,7 +724,7 @@ export const KeyboardNavigationMixin = (superClass) =>
723
724
 
724
725
  /** @private */
725
726
  _onKeyUp(e) {
726
- if (!/^( |SpaceBar)$/.test(e.key) || this.interacting) {
727
+ if (!/^( |SpaceBar)$/u.test(e.key) || this.interacting) {
727
728
  return;
728
729
  }
729
730
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2016 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import type { Constructor } from '@open-wc/dedupe-mixin';
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2016 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
+ import { iterateChildren } from './vaadin-grid-helpers.js';
6
7
 
7
8
  /**
8
9
  * @polymerMixin
@@ -78,7 +79,7 @@ export const RowDetailsMixin = (superClass) =>
78
79
 
79
80
  if (this._columnTree) {
80
81
  // Only update the rows if the column tree has already been initialized
81
- Array.from(this.$.items.children).forEach((row) => {
82
+ iterateChildren(this.$.items, (row) => {
82
83
  if (!row.querySelector('[part~=details-cell]')) {
83
84
  this._updateRow(row, this._columnTree[this._columnTree.length - 1]);
84
85
  const isDetailsOpened = this._isDetailsOpened(row._item);
@@ -95,7 +96,7 @@ export const RowDetailsMixin = (superClass) =>
95
96
  return;
96
97
  }
97
98
 
98
- [...this.$.items.children].forEach((row) => {
99
+ iterateChildren(this.$.items, (row) => {
99
100
  // Re-renders the row to possibly close the previously opened details.
100
101
  if (row.hasAttribute('details-opened')) {
101
102
  this._updateItem(row, row._item);
@@ -162,7 +163,7 @@ export const RowDetailsMixin = (superClass) =>
162
163
 
163
164
  /** @protected */
164
165
  _updateDetailsCellHeights() {
165
- [...this.$.items.children].forEach((row) => {
166
+ iterateChildren(this.$.items, (row) => {
166
167
  this._updateDetailsCellHeight(row);
167
168
  });
168
169
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2016 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import type { Constructor } from '@open-wc/dedupe-mixin';
@@ -1,10 +1,11 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2016 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { animationFrame, microTask, timeOut } from '@vaadin/component-base/src/async.js';
7
7
  import { Debouncer } from '@vaadin/component-base/src/debounce.js';
8
+ import { getNormalizedScrollLeft } from '@vaadin/component-base/src/dir-utils.js';
8
9
  import { ResizeMixin } from '@vaadin/component-base/src/resize-mixin.js';
9
10
 
10
11
  const timeouts = {
@@ -41,6 +42,11 @@ export const ScrollMixin = (superClass) =>
41
42
  };
42
43
  }
43
44
 
45
+ /** @private */
46
+ get _scrollLeft() {
47
+ return this.$.table.scrollLeft;
48
+ }
49
+
44
50
  /** @private */
45
51
  get _scrollTop() {
46
52
  return this.$.table.scrollTop;
@@ -54,11 +60,6 @@ export const ScrollMixin = (superClass) =>
54
60
  this.$.table.scrollTop = top;
55
61
  }
56
62
 
57
- /** @private */
58
- get _scrollLeft() {
59
- return this.$.table.scrollLeft;
60
- }
61
-
62
63
  /** @protected */
63
64
  ready() {
64
65
  super.ready();
@@ -157,7 +158,7 @@ export const ScrollMixin = (superClass) =>
157
158
  overflow += ' top';
158
159
  }
159
160
 
160
- const scrollLeft = this.__getNormalizedScrollLeft(table);
161
+ const scrollLeft = getNormalizedScrollLeft(table, this.getAttribute('dir'));
161
162
  if (scrollLeft > 0) {
162
163
  overflow += ' start';
163
164
  }
@@ -167,7 +168,7 @@ export const ScrollMixin = (superClass) =>
167
168
  }
168
169
 
169
170
  if (this.__isRTL) {
170
- overflow = overflow.replace(/start|end/gi, (matched) => {
171
+ overflow = overflow.replace(/start|end/giu, (matched) => {
171
172
  return matched === 'start' ? 'end' : 'start';
172
173
  });
173
174
  }
@@ -255,7 +256,7 @@ export const ScrollMixin = (superClass) =>
255
256
  const scrollWidth = this.$.table.scrollWidth;
256
257
  const clientWidth = this.$.table.clientWidth;
257
258
  const scrollLeft = Math.max(0, this.$.table.scrollLeft);
258
- const normalizedScrollLeft = this.__getNormalizedScrollLeft(this.$.table);
259
+ const normalizedScrollLeft = getNormalizedScrollLeft(this.$.table, this.getAttribute('dir'));
259
260
 
260
261
  // Position header, footer and items container
261
262
  const transform = `translate(${-scrollLeft}px, 0)`;