@vaadin/grid 24.3.0-alpha1 → 24.3.0-alpha3

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 (46) hide show
  1. package/package.json +10 -10
  2. package/src/vaadin-grid-array-data-provider-mixin.js +1 -1
  3. package/src/vaadin-grid-column-group-mixin.d.ts +20 -0
  4. package/src/vaadin-grid-column-group-mixin.js +369 -0
  5. package/src/vaadin-grid-column-group.d.ts +4 -14
  6. package/src/vaadin-grid-column-group.js +5 -355
  7. package/src/vaadin-grid-column-mixin.d.ts +170 -0
  8. package/src/vaadin-grid-column-mixin.js +922 -0
  9. package/src/vaadin-grid-column.d.ts +11 -138
  10. package/src/vaadin-grid-column.js +3 -876
  11. package/src/vaadin-grid-data-provider-mixin.d.ts +6 -5
  12. package/src/vaadin-grid-data-provider-mixin.js +38 -7
  13. package/src/vaadin-grid-drag-and-drop-mixin.js +1 -1
  14. package/src/vaadin-grid-filter-column-mixin.d.ts +22 -0
  15. package/src/vaadin-grid-filter-column-mixin.js +100 -0
  16. package/src/vaadin-grid-filter-column.d.ts +9 -11
  17. package/src/vaadin-grid-filter-column.js +3 -90
  18. package/src/vaadin-grid-filter-element-mixin.d.ts +34 -0
  19. package/src/vaadin-grid-filter-element-mixin.js +99 -0
  20. package/src/vaadin-grid-filter.d.ts +4 -21
  21. package/src/vaadin-grid-filter.js +5 -84
  22. package/src/vaadin-grid-keyboard-navigation-mixin.js +16 -3
  23. package/src/vaadin-grid-mixin.js +11 -8
  24. package/src/vaadin-grid-scroll-mixin.js +1 -1
  25. package/src/vaadin-grid-selection-column-mixin.d.ts +24 -0
  26. package/src/vaadin-grid-selection-column-mixin.js +194 -0
  27. package/src/vaadin-grid-selection-column.d.ts +13 -17
  28. package/src/vaadin-grid-selection-column.js +4 -186
  29. package/src/vaadin-grid-sort-column-mixin.d.ts +36 -0
  30. package/src/vaadin-grid-sort-column-mixin.js +97 -0
  31. package/src/vaadin-grid-sort-column.d.ts +8 -26
  32. package/src/vaadin-grid-sort-column.js +3 -87
  33. package/src/vaadin-grid-sorter-mixin.d.ts +44 -0
  34. package/src/vaadin-grid-sorter-mixin.js +198 -0
  35. package/src/vaadin-grid-sorter.d.ts +3 -32
  36. package/src/vaadin-grid-sorter.js +5 -181
  37. package/src/vaadin-grid-tree-column-mixin.d.ts +18 -0
  38. package/src/vaadin-grid-tree-column-mixin.js +92 -0
  39. package/src/vaadin-grid-tree-column.d.ts +9 -7
  40. package/src/vaadin-grid-tree-column.js +3 -82
  41. package/src/vaadin-grid-tree-toggle-mixin.d.ts +39 -0
  42. package/src/vaadin-grid-tree-toggle-mixin.js +151 -0
  43. package/src/vaadin-grid-tree-toggle.d.ts +4 -27
  44. package/src/vaadin-grid-tree-toggle.js +9 -141
  45. package/web-types.json +331 -126
  46. package/web-types.lit.json +114 -58
@@ -5,11 +5,9 @@
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
- import { timeOut } from '@vaadin/component-base/src/async.js';
9
- import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
10
- import { Debouncer } from '@vaadin/component-base/src/debounce.js';
11
8
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
12
- import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
9
+ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin';
10
+ import { GridFilterElementMixin } from './vaadin-grid-filter-element-mixin.js';
13
11
 
14
12
  /**
15
13
  * `<vaadin-grid-filter>` is a helper element for the `<vaadin-grid>` that provides out-of-the-box UI controls,
@@ -38,93 +36,16 @@ import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
38
36
  *
39
37
  * @customElement
40
38
  * @extends HTMLElement
39
+ * @mixes GridFilterElementMixin
41
40
  */
42
- class GridFilter extends ControllerMixin(PolymerElement) {
41
+ class GridFilter extends GridFilterElementMixin(ThemableMixin(PolymerElement)) {
43
42
  static get template() {
44
- return html`
45
- <style>
46
- :host {
47
- display: inline-flex;
48
- max-width: 100%;
49
- }
50
-
51
- ::slotted(*) {
52
- width: 100%;
53
- box-sizing: border-box;
54
- }
55
- </style>
56
- <slot></slot>
57
- `;
43
+ return html`<slot></slot>`;
58
44
  }
59
45
 
60
46
  static get is() {
61
47
  return 'vaadin-grid-filter';
62
48
  }
63
-
64
- static get properties() {
65
- return {
66
- /**
67
- * JS Path of the property in the item used for filtering the data.
68
- */
69
- path: String,
70
-
71
- /**
72
- * Current filter value.
73
- */
74
- value: {
75
- type: String,
76
- notify: true,
77
- },
78
-
79
- /** @private */
80
- _textField: {
81
- type: Object,
82
- },
83
- };
84
- }
85
-
86
- static get observers() {
87
- return ['_filterChanged(path, value, _textField)'];
88
- }
89
-
90
- /** @protected */
91
- ready() {
92
- super.ready();
93
-
94
- this._filterController = new SlotController(this, '', 'vaadin-text-field', {
95
- initializer: (field) => {
96
- field.addEventListener('value-changed', (e) => {
97
- this.value = e.detail.value;
98
- });
99
-
100
- this._textField = field;
101
- },
102
- });
103
- this.addController(this._filterController);
104
- }
105
-
106
- /** @private */
107
- _filterChanged(path, value, textField) {
108
- if (path === undefined || value === undefined || !textField) {
109
- return;
110
- }
111
- if (this._previousValue === undefined && value === '') {
112
- return;
113
- }
114
-
115
- textField.value = value;
116
- this._previousValue = value;
117
-
118
- this._debouncerFilterChanged = Debouncer.debounce(this._debouncerFilterChanged, timeOut.after(200), () => {
119
- this.dispatchEvent(new CustomEvent('filter-changed', { bubbles: true }));
120
- });
121
- }
122
-
123
- focus() {
124
- if (this._textField) {
125
- this._textField.focus();
126
- }
127
- }
128
49
  }
129
50
 
130
51
  defineCustomElement(GridFilter);
@@ -443,7 +443,7 @@ export const KeyboardNavigationMixin = (superClass) =>
443
443
  __navigateRows(dy, activeRow, activeCell) {
444
444
  const currentRowIndex = this.__getIndexInGroup(activeRow, this._focusedItemIndex);
445
445
  const activeRowGroup = activeRow.parentNode;
446
- const maxRowIndex = (activeRowGroup === this.$.items ? this._effectiveSize : activeRowGroup.children.length) - 1;
446
+ const maxRowIndex = (activeRowGroup === this.$.items ? this._flatSize : activeRowGroup.children.length) - 1;
447
447
 
448
448
  // Index of the destination row
449
449
  let dstRowIndex = Math.max(0, Math.min(currentRowIndex + dy, maxRowIndex));
@@ -842,9 +842,12 @@ export const KeyboardNavigationMixin = (superClass) =>
842
842
  }
843
843
 
844
844
  if (cell) {
845
- // Fire a public event for cell.
846
845
  const context = this.getEventContext(e);
847
- cell.dispatchEvent(new CustomEvent('cell-focus', { bubbles: true, composed: true, detail: { context } }));
846
+ this.__pendingBodyCellFocus = this.loading && context.section === 'body';
847
+ if (!this.__pendingBodyCellFocus) {
848
+ // Fire a cell-focus event for the cell
849
+ cell.dispatchEvent(new CustomEvent('cell-focus', { bubbles: true, composed: true, detail: { context } }));
850
+ }
848
851
  this._focusedCell = cell._focusButton || cell;
849
852
 
850
853
  if (isKeyboardActive() && e.target === cell) {
@@ -858,6 +861,16 @@ export const KeyboardNavigationMixin = (superClass) =>
858
861
  this._detectFocusedItemIndex(e);
859
862
  }
860
863
 
864
+ /**
865
+ * @private
866
+ */
867
+ __dispatchPendingBodyCellFocus() {
868
+ // If the body cell focus was pending, dispatch the event once loading is done
869
+ if (this.__pendingBodyCellFocus && this.shadowRoot.activeElement === this._itemsFocusable) {
870
+ this._itemsFocusable.dispatchEvent(new Event('focusin', { bubbles: true, composed: true }));
871
+ }
872
+ }
873
+
861
874
  /**
862
875
  * Get the focusable element depending on the current focus mode.
863
876
  * It can be a row, a cell, or a focusable div inside a cell.
@@ -88,7 +88,7 @@ export const GridMixin = (superClass) =>
88
88
  static get observers() {
89
89
  return [
90
90
  '_columnTreeChanged(_columnTree, _columnTree.*)',
91
- '_effectiveSizeChanged(_effectiveSize, __virtualizer, _hasData, _columnTree)',
91
+ '_flatSizeChanged(_flatSize, __virtualizer, _hasData, _columnTree)',
92
92
  ];
93
93
  }
94
94
 
@@ -294,20 +294,20 @@ export const GridMixin = (superClass) =>
294
294
  }
295
295
 
296
296
  /** @private */
297
- _effectiveSizeChanged(effectiveSize, virtualizer, hasData, columnTree) {
297
+ _flatSizeChanged(flatSize, virtualizer, hasData, columnTree) {
298
298
  if (virtualizer && hasData && columnTree) {
299
299
  // Changing the virtualizer size may result in the row with focus getting hidden
300
300
  const cell = this.shadowRoot.activeElement;
301
301
  const cellCoordinates = this.__getBodyCellCoordinates(cell);
302
302
 
303
303
  const previousSize = virtualizer.size || 0;
304
- virtualizer.size = effectiveSize;
304
+ virtualizer.size = flatSize;
305
305
 
306
306
  // Request an update for the previous last row to have the "last" state removed
307
307
  virtualizer.update(previousSize - 1, previousSize - 1);
308
- if (effectiveSize < previousSize) {
308
+ if (flatSize < previousSize) {
309
309
  // Size was decreased, so the new last row requires an explicit update
310
- virtualizer.update(effectiveSize - 1, effectiveSize - 1);
310
+ virtualizer.update(flatSize - 1, flatSize - 1);
311
311
  }
312
312
 
313
313
  // If the focused cell's parent row got hidden by the size change, focus the corresponding new cell
@@ -339,7 +339,10 @@ export const GridMixin = (superClass) =>
339
339
  return 0;
340
340
  }
341
341
 
342
- const columnWidth = Math.max(this.__getIntrinsicWidth(col), this.__getDistributedWidth(col.parentElement, col));
342
+ const columnWidth = Math.max(
343
+ this.__getIntrinsicWidth(col),
344
+ this.__getDistributedWidth((col.assignedSlot || col).parentElement, col),
345
+ );
343
346
 
344
347
  // We're processing a regular grid-column and not a grid-column-group
345
348
  if (!innerColumn) {
@@ -697,7 +700,7 @@ export const GridMixin = (superClass) =>
697
700
  column._emptyCells.push(cell);
698
701
  }
699
702
  }
700
- cell.setAttribute('part', `cell ${section}-cell`);
703
+ cell.part.add('cell', `${section}-cell`);
701
704
  }
702
705
 
703
706
  if (!cell._content.parentElement) {
@@ -801,7 +804,7 @@ export const GridMixin = (superClass) =>
801
804
  _updateRowOrderParts(row, index = row.index) {
802
805
  updateBooleanRowStates(row, {
803
806
  first: index === 0,
804
- last: index === this._effectiveSize - 1,
807
+ last: index === this._flatSize - 1,
805
808
  odd: index % 2 !== 0,
806
809
  even: index % 2 === 0,
807
810
  });
@@ -160,7 +160,7 @@ export const ScrollMixin = (superClass) =>
160
160
  * @protected
161
161
  */
162
162
  _scrollToFlatIndex(index) {
163
- index = Math.min(this._effectiveSize - 1, Math.max(0, index));
163
+ index = Math.min(this._flatSize - 1, Math.max(0, index));
164
164
  this.__virtualizer.scrollToIndex(index);
165
165
  this.__scrollIntoViewport(index);
166
166
  }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import type { Constructor } from '@open-wc/dedupe-mixin';
7
+ import { GridSelectionColumnBaseMixinClass } from './vaadin-grid-selection-column-base-mixin.js';
8
+
9
+ /**
10
+ * Fired when the `selectAll` property changes.
11
+ */
12
+ export type GridSelectionColumnSelectAllChangedEvent = CustomEvent<{ value: boolean }>;
13
+
14
+ export interface GridSelectionColumnCustomEventMap {
15
+ 'select-all-changed': GridSelectionColumnSelectAllChangedEvent;
16
+ }
17
+
18
+ export interface GridSelectionColumnEventMap extends HTMLElementEventMap, GridSelectionColumnCustomEventMap {}
19
+
20
+ export declare function GridSelectionColumnMixin<TItem, T extends Constructor<HTMLElement>>(
21
+ superclass: T,
22
+ ): Constructor<GridSelectionColumnMixinClass<TItem>> & T;
23
+
24
+ export declare class GridSelectionColumnMixinClass<TItem> extends GridSelectionColumnBaseMixinClass<TItem> {}
@@ -0,0 +1,194 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { GridSelectionColumnBaseMixin } from './vaadin-grid-selection-column-base-mixin.js';
7
+
8
+ /**
9
+ * @polymerMixin
10
+ */
11
+ export const GridSelectionColumnMixin = (superClass) =>
12
+ class extends GridSelectionColumnBaseMixin(superClass) {
13
+ static get properties() {
14
+ return {
15
+ /**
16
+ * The previous state of activeItem. When activeItem turns to `null`,
17
+ * previousActiveItem will have an Object with just unselected activeItem
18
+ * @private
19
+ */
20
+ __previousActiveItem: Object,
21
+ };
22
+ }
23
+
24
+ static get observers() {
25
+ return ['__onSelectAllChanged(selectAll)'];
26
+ }
27
+
28
+ constructor() {
29
+ super();
30
+
31
+ this.__boundOnActiveItemChanged = this.__onActiveItemChanged.bind(this);
32
+ this.__boundOnDataProviderChanged = this.__onDataProviderChanged.bind(this);
33
+ this.__boundOnSelectedItemsChanged = this.__onSelectedItemsChanged.bind(this);
34
+ }
35
+
36
+ /** @protected */
37
+ disconnectedCallback() {
38
+ this._grid.removeEventListener('active-item-changed', this.__boundOnActiveItemChanged);
39
+ this._grid.removeEventListener('data-provider-changed', this.__boundOnDataProviderChanged);
40
+ this._grid.removeEventListener('filter-changed', this.__boundOnSelectedItemsChanged);
41
+ this._grid.removeEventListener('selected-items-changed', this.__boundOnSelectedItemsChanged);
42
+
43
+ super.disconnectedCallback();
44
+ }
45
+
46
+ /** @protected */
47
+ connectedCallback() {
48
+ super.connectedCallback();
49
+ if (this._grid) {
50
+ this._grid.addEventListener('active-item-changed', this.__boundOnActiveItemChanged);
51
+ this._grid.addEventListener('data-provider-changed', this.__boundOnDataProviderChanged);
52
+ this._grid.addEventListener('filter-changed', this.__boundOnSelectedItemsChanged);
53
+ this._grid.addEventListener('selected-items-changed', this.__boundOnSelectedItemsChanged);
54
+ }
55
+ }
56
+
57
+ /** @private */
58
+ __onSelectAllChanged(selectAll) {
59
+ if (selectAll === undefined || !this._grid) {
60
+ return;
61
+ }
62
+
63
+ if (!this.__selectAllInitialized) {
64
+ // The initial value for selectAll property was applied, avoid clearing pre-selected items
65
+ this.__selectAllInitialized = true;
66
+ return;
67
+ }
68
+
69
+ if (this._selectAllChangeLock) {
70
+ return;
71
+ }
72
+
73
+ if (selectAll && this.__hasArrayDataProvider()) {
74
+ this.__withFilteredItemsArray((items) => {
75
+ this._grid.selectedItems = items;
76
+ });
77
+ } else {
78
+ this._grid.selectedItems = [];
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Return true if array `a` contains all the items in `b`
84
+ * We need this when sorting or to preserve selection after filtering.
85
+ * @private
86
+ */
87
+ __arrayContains(a, b) {
88
+ return Array.isArray(a) && Array.isArray(b) && b.every((i) => a.includes(i));
89
+ }
90
+
91
+ /**
92
+ * Override a method from `GridSelectionColumnBaseMixin` to handle the user
93
+ * selecting all items.
94
+ *
95
+ * @protected
96
+ * @override
97
+ */
98
+ _selectAll() {
99
+ this.selectAll = true;
100
+ }
101
+
102
+ /**
103
+ * Override a method from `GridSelectionColumnBaseMixin` to handle the user
104
+ * deselecting all items.
105
+ *
106
+ * @protected
107
+ * @override
108
+ */
109
+ _deselectAll() {
110
+ this.selectAll = false;
111
+ }
112
+
113
+ /**
114
+ * Override a method from `GridSelectionColumnBaseMixin` to handle the user
115
+ * selecting an item.
116
+ *
117
+ * @param {Object} item the item to select
118
+ * @protected
119
+ * @override
120
+ */
121
+ _selectItem(item) {
122
+ this._grid.selectItem(item);
123
+ }
124
+
125
+ /**
126
+ * Override a method from `GridSelectionColumnBaseMixin` to handle the user
127
+ * deselecting an item.
128
+ *
129
+ * @param {Object} item the item to deselect
130
+ * @protected
131
+ * @override
132
+ */
133
+ _deselectItem(item) {
134
+ this._grid.deselectItem(item);
135
+ }
136
+
137
+ /** @private */
138
+ __onActiveItemChanged(e) {
139
+ const activeItem = e.detail.value;
140
+ if (this.autoSelect) {
141
+ const item = activeItem || this.__previousActiveItem;
142
+ if (item) {
143
+ this._grid._toggleItem(item);
144
+ }
145
+ }
146
+ this.__previousActiveItem = activeItem;
147
+ }
148
+
149
+ /** @private */
150
+ __hasArrayDataProvider() {
151
+ return Array.isArray(this._grid.items) && !!this._grid.dataProvider;
152
+ }
153
+
154
+ /** @private */
155
+ __onSelectedItemsChanged() {
156
+ this._selectAllChangeLock = true;
157
+ if (this.__hasArrayDataProvider()) {
158
+ this.__withFilteredItemsArray((items) => {
159
+ if (!this._grid.selectedItems.length) {
160
+ this.selectAll = false;
161
+ this._indeterminate = false;
162
+ } else if (this.__arrayContains(this._grid.selectedItems, items)) {
163
+ this.selectAll = true;
164
+ this._indeterminate = false;
165
+ } else {
166
+ this.selectAll = false;
167
+ this._indeterminate = true;
168
+ }
169
+ });
170
+ }
171
+ this._selectAllChangeLock = false;
172
+ }
173
+
174
+ /** @private */
175
+ __onDataProviderChanged() {
176
+ this._selectAllHidden = !Array.isArray(this._grid.items);
177
+ }
178
+
179
+ /**
180
+ * Assuming the grid uses an items array data provider, fetches all the filtered items
181
+ * from the data provider and invokes the callback with the resulting array.
182
+ *
183
+ * @private
184
+ */
185
+ __withFilteredItemsArray(callback) {
186
+ const params = {
187
+ page: 0,
188
+ pageSize: Infinity,
189
+ sortOrders: [],
190
+ filters: this._grid._mapFilters(),
191
+ };
192
+ this._grid.dataProvider(params, (items) => callback(items));
193
+ }
194
+ };
@@ -4,19 +4,14 @@
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';
7
- import { GridColumn } from './vaadin-grid-column.js';
8
- import type { GridSelectionColumnBaseMixinClass } from './vaadin-grid-selection-column-base-mixin.js';
7
+ import type { GridColumnMixin } from './vaadin-grid-column.js';
8
+ import type { GridColumn } from './vaadin-grid-column.js';
9
+ import type {
10
+ GridSelectionColumnEventMap,
11
+ GridSelectionColumnMixinClass,
12
+ } from './vaadin-grid-selection-column-mixin.js';
9
13
 
10
- /**
11
- * Fired when the `selectAll` property changes.
12
- */
13
- export type GridSelectionColumnSelectAllChangedEvent = CustomEvent<{ value: boolean }>;
14
-
15
- export interface GridSelectionColumnCustomEventMap {
16
- 'select-all-changed': GridSelectionColumnSelectAllChangedEvent;
17
- }
18
-
19
- export interface GridSelectionColumnEventMap extends HTMLElementEventMap, GridSelectionColumnCustomEventMap {}
14
+ export * from './vaadin-grid-selection-column-mixin.js';
20
15
 
21
16
  /**
22
17
  * `<vaadin-grid-selection-column>` is a helper element for the `<vaadin-grid>`
@@ -39,10 +34,13 @@ export interface GridSelectionColumnEventMap extends HTMLElementEventMap, GridSe
39
34
  * selection for all the items at once.
40
35
  *
41
36
  * __The default content can also be overridden__
42
- *
43
- * @fires {CustomEvent} select-all-changed - Fired when the `selectAll` property changes.
44
37
  */
45
- declare class GridSelectionColumn<TItem = GridDefaultItem> extends GridColumn<TItem> {
38
+ declare class GridSelectionColumn<TItem = GridDefaultItem> extends HTMLElement {}
39
+
40
+ interface GridSelectionColumn<TItem = GridDefaultItem>
41
+ extends GridSelectionColumnMixinClass<TItem>,
42
+ GridColumnMixin<TItem, GridColumn<TItem>>,
43
+ GridColumn<TItem> {
46
44
  addEventListener<K extends keyof GridSelectionColumnEventMap>(
47
45
  type: K,
48
46
  listener: (this: GridSelectionColumn<TItem>, ev: GridSelectionColumnEventMap[K]) => void,
@@ -56,8 +54,6 @@ declare class GridSelectionColumn<TItem = GridDefaultItem> extends GridColumn<TI
56
54
  ): void;
57
55
  }
58
56
 
59
- interface GridSelectionColumn<TItem = GridDefaultItem> extends GridSelectionColumnBaseMixinClass<TItem> {}
60
-
61
57
  declare global {
62
58
  interface HTMLElementTagNameMap {
63
59
  'vaadin-grid-selection-column': GridSelectionColumn<GridDefaultItem>;