@vaadin/grid 24.2.0-beta2 → 24.2.0-beta3

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 (34) 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 +156 -0
  8. package/src/vaadin-grid-column-mixin.js +887 -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 -30
  12. package/src/vaadin-grid-data-provider-mixin.js +100 -241
  13. package/src/vaadin-grid-drag-and-drop-mixin.js +1 -1
  14. package/src/vaadin-grid-filter-element-mixin.d.ts +34 -0
  15. package/src/vaadin-grid-filter-element-mixin.js +99 -0
  16. package/src/vaadin-grid-filter.d.ts +4 -21
  17. package/src/vaadin-grid-filter.js +5 -84
  18. package/src/vaadin-grid-keyboard-navigation-mixin.js +2 -2
  19. package/src/vaadin-grid-mixin.js +10 -10
  20. package/src/vaadin-grid-scroll-mixin.js +1 -1
  21. package/src/vaadin-grid-sorter-mixin.d.ts +44 -0
  22. package/src/vaadin-grid-sorter-mixin.js +198 -0
  23. package/src/vaadin-grid-sorter.d.ts +3 -32
  24. package/src/vaadin-grid-sorter.js +5 -181
  25. package/src/vaadin-grid-tree-column-mixin.d.ts +19 -0
  26. package/src/vaadin-grid-tree-column-mixin.js +92 -0
  27. package/src/vaadin-grid-tree-column.d.ts +9 -7
  28. package/src/vaadin-grid-tree-column.js +3 -82
  29. package/src/vaadin-grid-tree-toggle-mixin.d.ts +39 -0
  30. package/src/vaadin-grid-tree-toggle-mixin.js +151 -0
  31. package/src/vaadin-grid-tree-toggle.d.ts +4 -27
  32. package/src/vaadin-grid-tree-toggle.js +9 -141
  33. package/web-types.json +98 -98
  34. package/web-types.lit.json +42 -42
@@ -4,6 +4,10 @@
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';
7
+ import type {
8
+ DataProvider,
9
+ DataProviderCallback,
10
+ } from '@vaadin/component-base/src/data-provider-controller/data-provider-controller.js';
7
11
  import { GridSorterDirection } from './vaadin-grid-sorter.js';
8
12
 
9
13
  export { GridSorterDirection };
@@ -18,7 +22,7 @@ export interface GridSorterDefinition {
18
22
  direction: GridSorterDirection;
19
23
  }
20
24
 
21
- export type GridDataProviderCallback<TItem> = (items: TItem[], size?: number) => void;
25
+ export type GridDataProviderCallback<TItem> = DataProviderCallback<TItem>;
22
26
 
23
27
  export type GridDataProviderParams<TItem> = {
24
28
  page: number;
@@ -28,35 +32,7 @@ export type GridDataProviderParams<TItem> = {
28
32
  parentItem?: TItem;
29
33
  };
30
34
 
31
- export type GridDataProvider<TItem> = (
32
- params: GridDataProviderParams<TItem>,
33
- callback: GridDataProviderCallback<TItem>,
34
- ) => void;
35
-
36
- export declare class ItemCache<TItem> {
37
- grid: HTMLElement;
38
- parentCache: ItemCache<TItem> | undefined;
39
- parentItem: TItem | undefined;
40
- itemCaches: object | null;
41
- items: object | null;
42
- effectiveSize: number;
43
- size: number;
44
- pendingRequests: object | null;
45
-
46
- constructor(grid: HTMLElement, parentCache: ItemCache<TItem> | undefined, parentItem: TItem | undefined);
47
-
48
- isLoading(): boolean;
49
-
50
- getItemForIndex(index: number): TItem | undefined;
51
-
52
- updateSize(): void;
53
-
54
- ensureSubCacheForScaledIndex(scaledIndex: number): void;
55
-
56
- getCacheAndIndex(index: number): { cache: ItemCache<TItem>; scaledIndex: number };
57
-
58
- getFlatIndex(scaledIndex: number): number;
59
- }
35
+ export type GridDataProvider<TItem> = DataProvider<TItem, GridDataProviderParams<TItem>>;
60
36
 
61
37
  export declare function DataProviderMixin<TItem, T extends Constructor<HTMLElement>>(
62
38
  base: T,
@@ -4,116 +4,11 @@
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { timeOut } from '@vaadin/component-base/src/async.js';
7
+ import { DataProviderController } from '@vaadin/component-base/src/data-provider-controller/data-provider-controller.js';
7
8
  import { Debouncer } from '@vaadin/component-base/src/debounce.js';
8
9
  import { get } from '@vaadin/component-base/src/path-utils.js';
9
10
  import { getBodyRowCells, updateCellsPart, updateState } from './vaadin-grid-helpers.js';
10
11
 
11
- /**
12
- * @private
13
- */
14
- export const ItemCache = class ItemCache {
15
- /**
16
- * @param {!HTMLElement} grid
17
- * @param {!ItemCache | undefined} parentCache
18
- * @param {!GridItem | undefined} parentItem
19
- */
20
- constructor(grid, parentCache, parentItem) {
21
- /** @type {!HTMLElement} */
22
- this.grid = grid;
23
- /** @type {!ItemCache | undefined} */
24
- this.parentCache = parentCache;
25
- /** @type {!GridItem | undefined} */
26
- this.parentItem = parentItem;
27
- /** @type {object} */
28
- this.itemCaches = {};
29
- /** @type {object[]} */
30
- this.items = [];
31
- /** @type {number} */
32
- this.effectiveSize = 0;
33
- /** @type {number} */
34
- this.size = 0;
35
- /** @type {object} */
36
- this.pendingRequests = {};
37
- }
38
-
39
- /**
40
- * @return {boolean}
41
- */
42
- isLoading() {
43
- return Boolean(
44
- Object.keys(this.pendingRequests).length ||
45
- Object.keys(this.itemCaches).filter((index) => {
46
- return this.itemCaches[index].isLoading();
47
- })[0],
48
- );
49
- }
50
-
51
- /**
52
- * @param {number} index
53
- * @return {!GridItem | undefined}
54
- */
55
- getItemForIndex(index) {
56
- const { cache, scaledIndex } = this.getCacheAndIndex(index);
57
- return cache.items[scaledIndex];
58
- }
59
-
60
- updateSize() {
61
- this.effectiveSize =
62
- !this.parentItem || this.grid._isExpanded(this.parentItem)
63
- ? this.size +
64
- Object.keys(this.itemCaches).reduce((prev, curr) => {
65
- const subCache = this.itemCaches[curr];
66
- subCache.updateSize();
67
- return prev + subCache.effectiveSize;
68
- }, 0)
69
- : 0;
70
- }
71
-
72
- /**
73
- * @param {number} scaledIndex
74
- */
75
- ensureSubCacheForScaledIndex(scaledIndex) {
76
- if (!this.itemCaches[scaledIndex]) {
77
- const subCache = new ItemCache(this.grid, this, this.items[scaledIndex]);
78
- this.itemCaches[scaledIndex] = subCache;
79
- this.grid._loadPage(0, subCache);
80
- }
81
- }
82
-
83
- /**
84
- * @param {number} index
85
- * @return {{cache: !ItemCache, scaledIndex: number}}
86
- */
87
- getCacheAndIndex(index) {
88
- let thisLevelIndex = index;
89
- for (const [index, subCache] of Object.entries(this.itemCaches)) {
90
- const numberIndex = Number(index);
91
- if (thisLevelIndex <= numberIndex) {
92
- return { cache: this, scaledIndex: thisLevelIndex };
93
- } else if (thisLevelIndex <= numberIndex + subCache.effectiveSize) {
94
- return subCache.getCacheAndIndex(thisLevelIndex - numberIndex - 1);
95
- }
96
- thisLevelIndex -= subCache.effectiveSize;
97
- }
98
- return { cache: this, scaledIndex: thisLevelIndex };
99
- }
100
-
101
- /**
102
- * Gets the scaled index as flattened index on this cache level.
103
- * In practice, this means that the effective size of any expanded
104
- * subcaches preceding the index are added to the value.
105
- * @param {number} scaledIndex
106
- * @return {number} The flat index on this cache level.
107
- */
108
- getFlatIndex(scaledIndex) {
109
- const clampedIndex = Math.max(0, Math.min(this.size - 1, scaledIndex));
110
-
111
- return Object.entries(this.itemCaches).reduce((prev, [index, subCache]) => {
112
- return clampedIndex > Number(index) ? prev + subCache.effectiveSize : prev;
113
- }, clampedIndex);
114
- }
115
- };
116
-
117
12
  /**
118
13
  * @polymerMixin
119
14
  */
@@ -181,18 +76,6 @@ export const DataProviderMixin = (superClass) =>
181
76
  reflectToAttribute: true,
182
77
  },
183
78
 
184
- /**
185
- * @type {!ItemCache}
186
- * @protected
187
- */
188
- _cache: {
189
- type: Object,
190
- value() {
191
- const cache = new ItemCache(this);
192
- return cache;
193
- },
194
- },
195
-
196
79
  /**
197
80
  * @protected
198
81
  */
@@ -244,12 +127,50 @@ export const DataProviderMixin = (superClass) =>
244
127
  return ['_sizeChanged(size)', '_expandedItemsChanged(expandedItems.*)'];
245
128
  }
246
129
 
130
+ constructor() {
131
+ super();
132
+
133
+ /** @type {DataProviderController} */
134
+ this._dataProviderController = new DataProviderController(this, {
135
+ size: this.size,
136
+ pageSize: this.pageSize,
137
+ isExpanded: this._isExpanded.bind(this),
138
+ dataProvider: this.dataProvider ? this.dataProvider.bind(this) : null,
139
+ dataProviderParams: () => {
140
+ return {
141
+ sortOrders: this._mapSorters(),
142
+ filters: this._mapFilters(),
143
+ };
144
+ },
145
+ });
146
+
147
+ this._dataProviderController.addEventListener('page-requested', this._onDataProviderPageRequested.bind(this));
148
+ this._dataProviderController.addEventListener('page-received', this._onDataProviderPageReceived.bind(this));
149
+ this._dataProviderController.addEventListener('page-loaded', this._onDataProviderPageLoaded.bind(this));
150
+ }
151
+
152
+ /**
153
+ * @protected
154
+ * @deprecated since 24.3 and will be removed in Vaadin 25.
155
+ */
156
+ get _cache() {
157
+ console.warn('<vaadin-grid> The `_cache` property is deprecated and will be removed in Vaadin 25.');
158
+ return this._dataProviderController.rootCache;
159
+ }
160
+
161
+ /**
162
+ * @protected
163
+ * @deprecated since 24.3 and will be removed in Vaadin 25.
164
+ */
165
+ get _effectiveSize() {
166
+ console.warn('<vaadin-grid> The `_effectiveSize` property is deprecated and will be removed in Vaadin 25.');
167
+ return this._flatSize;
168
+ }
169
+
247
170
  /** @private */
248
171
  _sizeChanged(size) {
249
- const delta = size - this._cache.size;
250
- this._cache.size += delta;
251
- this._cache.effectiveSize += delta;
252
- this._effectiveSize = this._cache.effectiveSize;
172
+ this._dataProviderController.setSize(size);
173
+ this._flatSize = this._dataProviderController.flatSize;
253
174
  }
254
175
 
255
176
  /** @private */
@@ -267,22 +188,22 @@ export const DataProviderMixin = (superClass) =>
267
188
  * @protected
268
189
  */
269
190
  _getItem(index, el) {
270
- if (index >= this._effectiveSize) {
191
+ if (index >= this._flatSize) {
271
192
  return;
272
193
  }
273
194
 
274
195
  el.index = index;
275
- const { cache, scaledIndex } = this._cache.getCacheAndIndex(index);
276
- const item = cache.items[scaledIndex];
196
+
197
+ const { item } = this._dataProviderController.getFlatIndexContext(index);
277
198
  if (item) {
278
199
  this.__updateLoading(el, false);
279
200
  this._updateItem(el, item);
280
201
  if (this._isExpanded(item)) {
281
- cache.ensureSubCacheForScaledIndex(scaledIndex);
202
+ this._dataProviderController.ensureFlatIndexHierarchy(index);
282
203
  }
283
204
  } else {
284
205
  this.__updateLoading(el, true);
285
- this._loadPage(this._getPageForIndex(scaledIndex), cache);
206
+ this._dataProviderController.ensureFlatIndexLoaded(index);
286
207
  }
287
208
  }
288
209
 
@@ -322,8 +243,8 @@ export const DataProviderMixin = (superClass) =>
322
243
 
323
244
  /** @private */
324
245
  _expandedItemsChanged() {
325
- this._cache.updateSize();
326
- this._effectiveSize = this._cache.effectiveSize;
246
+ this._dataProviderController.recalculateFlatSize();
247
+ this._flatSize = this._dataProviderController.flatSize;
327
248
  this.__updateVisibleRows();
328
249
  }
329
250
 
@@ -363,13 +284,8 @@ export const DataProviderMixin = (superClass) =>
363
284
  * @return {number}
364
285
  * @protected
365
286
  */
366
- _getIndexLevel(index) {
367
- let { cache } = this._cache.getCacheAndIndex(index);
368
- let level = 0;
369
- while (cache.parentCache) {
370
- cache = cache.parentCache;
371
- level += 1;
372
- }
287
+ _getIndexLevel(index = 0) {
288
+ const { level } = this._dataProviderController.getFlatIndexContext(index);
373
289
  return level;
374
290
  }
375
291
 
@@ -377,105 +293,70 @@ export const DataProviderMixin = (superClass) =>
377
293
  * @param {number} page
378
294
  * @param {ItemCache} cache
379
295
  * @protected
296
+ * @deprecated since 24.3 and will be removed in Vaadin 25.
380
297
  */
381
298
  _loadPage(page, cache) {
382
- // Make sure same page isn't requested multiple times.
383
- if (!cache.pendingRequests[page] && this.dataProvider) {
384
- this._setLoading(true);
385
- cache.pendingRequests[page] = true;
386
- const params = {
387
- page,
388
- pageSize: this.pageSize,
389
- sortOrders: this._mapSorters(),
390
- filters: this._mapFilters(),
391
- parentItem: cache.parentItem,
392
- };
393
-
394
- this.dataProvider(params, (items, size) => {
395
- if (size !== undefined) {
396
- cache.size = size;
397
- } else if (params.parentItem) {
398
- cache.size = items.length;
399
- }
299
+ console.warn('<vaadin-grid> The `_loadPage` method is deprecated and will be removed in Vaadin 25.');
300
+ this._dataProviderController.__loadCachePage(cache, page);
301
+ }
400
302
 
401
- // Populate the cache with new items
402
- items.forEach((item, itemsIndex) => {
403
- const itemIndex = page * this.pageSize + itemsIndex;
404
- cache.items[itemIndex] = item;
405
- });
406
-
407
- // With the new items added, update the cache size and the grid's effective size
408
- this._cache.updateSize();
409
- this._effectiveSize = this._cache.effectiveSize;
410
-
411
- // After updating the cache, check if some of the expanded items should have sub-caches loaded
412
- this._getRenderedRows().forEach((row) => {
413
- const { cache, scaledIndex } = this._cache.getCacheAndIndex(row.index);
414
- const item = cache.items[scaledIndex];
415
- if (item && this._isExpanded(item)) {
416
- cache.ensureSubCacheForScaledIndex(scaledIndex);
417
- }
418
- });
419
-
420
- this._hasData = true;
421
-
422
- // Remove the pending request
423
- delete cache.pendingRequests[page];
424
-
425
- // Schedule a debouncer to update the visible rows
426
- this._debouncerApplyCachedData = Debouncer.debounce(this._debouncerApplyCachedData, timeOut.after(0), () => {
427
- this._setLoading(false);
428
-
429
- this._getRenderedRows().forEach((row) => {
430
- const cachedItem = this._cache.getItemForIndex(row.index);
431
- if (cachedItem) {
432
- this._getItem(row.index, row);
433
- }
434
- });
435
-
436
- this.__scrollToPendingIndexes();
437
- });
438
-
439
- // If the grid is not loading anything, flush the debouncer immediately
440
- if (!this._cache.isLoading()) {
441
- this._debouncerApplyCachedData.flush();
442
- }
303
+ /** @protected */
304
+ _onDataProviderPageRequested() {
305
+ this._setLoading(true);
306
+ }
443
307
 
444
- // Notify that new data has been received
445
- this._onDataProviderPageLoaded();
446
- });
447
- }
308
+ /** @protected */
309
+ _onDataProviderPageReceived() {
310
+ // With the new items added, update the cache size and the grid's effective size
311
+ this._flatSize = this._dataProviderController.flatSize;
312
+
313
+ // After updating the cache, check if some of the expanded items should have sub-caches loaded
314
+ this._getRenderedRows().forEach((row) => {
315
+ this._dataProviderController.ensureFlatIndexHierarchy(row.index);
316
+ });
317
+
318
+ this._hasData = true;
448
319
  }
449
320
 
450
321
  /** @protected */
451
- _onDataProviderPageLoaded() {}
322
+ _onDataProviderPageLoaded() {
323
+ // Schedule a debouncer to update the visible rows
324
+ this._debouncerApplyCachedData = Debouncer.debounce(this._debouncerApplyCachedData, timeOut.after(0), () => {
325
+ this._setLoading(false);
326
+
327
+ this._getRenderedRows().forEach((row) => {
328
+ const { item } = this._dataProviderController.getFlatIndexContext(row.index);
329
+ if (item) {
330
+ this._getItem(row.index, row);
331
+ }
332
+ });
452
333
 
453
- /**
454
- * @param {number} index
455
- * @return {number}
456
- * @private
457
- */
458
- _getPageForIndex(index) {
459
- return Math.floor(index / this.pageSize);
334
+ this.__scrollToPendingIndexes();
335
+ });
336
+
337
+ // If the grid is not loading anything, flush the debouncer immediately
338
+ if (!this._dataProviderController.isLoading()) {
339
+ this._debouncerApplyCachedData.flush();
340
+ }
460
341
  }
461
342
 
462
343
  /**
463
344
  * Clears the cached pages and reloads data from dataprovider when needed.
464
345
  */
465
346
  clearCache() {
466
- this._cache = new ItemCache(this);
467
- this._cache.size = this.size || 0;
468
- this._cache.updateSize();
347
+ this._dataProviderController.clearCache();
469
348
  this._hasData = false;
470
349
  this.__updateVisibleRows();
471
350
 
472
- if (!this._effectiveSize) {
473
- this._loadPage(0, this._cache);
351
+ if (!this._flatSize) {
352
+ this._dataProviderController.loadFirstPage();
474
353
  }
475
354
  }
476
355
 
477
356
  /** @private */
478
357
  _pageSizeChanged(pageSize, oldPageSize) {
358
+ this._dataProviderController.setPageSize(pageSize);
359
+
479
360
  if (oldPageSize !== undefined && pageSize !== oldPageSize) {
480
361
  this.clearCache();
481
362
  }
@@ -483,7 +364,7 @@ export const DataProviderMixin = (superClass) =>
483
364
 
484
365
  /** @protected */
485
366
  _checkSize() {
486
- if (this.size === undefined && this._effectiveSize === 0) {
367
+ if (this.size === undefined && this._flatSize === 0) {
487
368
  console.warn(
488
369
  'The <vaadin-grid> needs the total number of items in' +
489
370
  ' order to display rows, which you can specify either by setting' +
@@ -495,6 +376,8 @@ export const DataProviderMixin = (superClass) =>
495
376
 
496
377
  /** @private */
497
378
  _dataProviderChanged(dataProvider, oldDataProvider) {
379
+ this._dataProviderController.setDataProvider(dataProvider ? dataProvider.bind(this) : null);
380
+
498
381
  if (oldDataProvider !== undefined) {
499
382
  this.clearCache();
500
383
  }
@@ -513,7 +396,7 @@ export const DataProviderMixin = (superClass) =>
513
396
  if (!this._hasData) {
514
397
  // Load data before adding rows to make sure they have content when
515
398
  // rendered for the first time.
516
- this._loadPage(0, this._cache);
399
+ this._dataProviderController.loadFirstPage();
517
400
  }
518
401
  }
519
402
 
@@ -563,39 +446,15 @@ export const DataProviderMixin = (superClass) =>
563
446
  // ending up in a loading state. Try scrolling to the index until the target
564
447
  // index stabilizes.
565
448
  let targetIndex;
566
- while (targetIndex !== (targetIndex = this.__getGlobalFlatIndex(indexes))) {
449
+ while (targetIndex !== (targetIndex = this._dataProviderController.getFlatIndexByPath(indexes))) {
567
450
  this._scrollToFlatIndex(targetIndex);
568
451
  }
569
452
 
570
- if (this._cache.isLoading() || !this.clientHeight) {
453
+ if (this._dataProviderController.isLoading() || !this.clientHeight) {
571
454
  this.__pendingScrollToIndexes = indexes;
572
455
  }
573
456
  }
574
457
 
575
- /**
576
- * Recursively returns the globally flat index of the item the given indexes point to.
577
- * Each index in the array points to a sub-item of the previous index.
578
- * Using `Infinity` as an index will point to the last item on the level.
579
- *
580
- * @param {!Array<number>} indexes
581
- * @param {!ItemCache} cache
582
- * @param {number} flatIndex
583
- * @return {number}
584
- * @private
585
- */
586
- __getGlobalFlatIndex([levelIndex, ...subIndexes], cache = this._cache, flatIndex = 0) {
587
- if (levelIndex === Infinity) {
588
- // Treat Infinity as the last index on the level
589
- levelIndex = cache.size - 1;
590
- }
591
- const flatIndexOnLevel = cache.getFlatIndex(levelIndex);
592
- const subCache = cache.itemCaches[levelIndex];
593
- if (subCache && subCache.effectiveSize && subIndexes.length) {
594
- return this.__getGlobalFlatIndex(subIndexes, subCache, flatIndex + flatIndexOnLevel + 1);
595
- }
596
- return flatIndex + flatIndexOnLevel;
597
- }
598
-
599
458
  /** @private */
600
459
  __scrollToPendingIndexes() {
601
460
  if (this.__pendingScrollToIndexes && this.$.items.children.length) {
@@ -211,7 +211,7 @@ export const DragAndDropMixin = (superClass) =>
211
211
 
212
212
  let row = e.composedPath().find((node) => node.localName === 'tr');
213
213
 
214
- if (!this._effectiveSize || this.dropMode === DropMode.ON_GRID) {
214
+ if (!this._flatSize || this.dropMode === DropMode.ON_GRID) {
215
215
  // The grid is empty or "on-grid" drop mode was used, always default to "empty"
216
216
  this._dropLocation = DropLocation.EMPTY;
217
217
  } else if (!row || row.parentNode !== this.$.items) {
@@ -0,0 +1,34 @@
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 type { ControllerMixinClass } from '@vaadin/component-base/src/controller-mixin.js';
8
+
9
+ /**
10
+ * Fired when the `value` property changes.
11
+ */
12
+ export type GridFilterValueChangedEvent = CustomEvent<{ value: string }>;
13
+
14
+ export interface GridFilterCustomEventMap {
15
+ 'value-changed': GridFilterValueChangedEvent;
16
+ }
17
+
18
+ export interface GridFilterEventMap extends HTMLElementEventMap, GridFilterCustomEventMap {}
19
+
20
+ export declare function GridFilterElementMixin<T extends Constructor<HTMLElement>>(
21
+ base: T,
22
+ ): Constructor<ControllerMixinClass> & Constructor<GridFilterElementMixinClass> & T;
23
+
24
+ declare class GridFilterElementMixinClass {
25
+ /**
26
+ * JS Path of the property in the item used for filtering the data.
27
+ */
28
+ path: string | null | undefined;
29
+
30
+ /**
31
+ * Current filter value.
32
+ */
33
+ value: string | null | undefined;
34
+ }
@@ -0,0 +1,99 @@
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 { timeOut } from '@vaadin/component-base/src/async.js';
7
+ import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
8
+ import { Debouncer } from '@vaadin/component-base/src/debounce.js';
9
+ import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
10
+ import { css, registerStyles } from '@vaadin/vaadin-themable-mixin';
11
+
12
+ registerStyles(
13
+ 'vaadin-grid-filter',
14
+ css`
15
+ :host {
16
+ display: inline-flex;
17
+ max-width: 100%;
18
+ }
19
+
20
+ ::slotted(*) {
21
+ width: 100%;
22
+ box-sizing: border-box;
23
+ }
24
+ `,
25
+ { moduleId: 'vaadin-grid-filter-styles' },
26
+ );
27
+
28
+ /**
29
+ * @polymerMixin
30
+ *
31
+ * @mixes ControllerMixin
32
+ */
33
+ export const GridFilterElementMixin = (superClass) =>
34
+ class extends ControllerMixin(superClass) {
35
+ static get properties() {
36
+ return {
37
+ /**
38
+ * JS Path of the property in the item used for filtering the data.
39
+ */
40
+ path: String,
41
+
42
+ /**
43
+ * Current filter value.
44
+ */
45
+ value: {
46
+ type: String,
47
+ notify: true,
48
+ },
49
+
50
+ /** @private */
51
+ _textField: {
52
+ type: Object,
53
+ },
54
+ };
55
+ }
56
+
57
+ static get observers() {
58
+ return ['_filterChanged(path, value, _textField)'];
59
+ }
60
+
61
+ /** @protected */
62
+ ready() {
63
+ super.ready();
64
+
65
+ this._filterController = new SlotController(this, '', 'vaadin-text-field', {
66
+ initializer: (field) => {
67
+ field.addEventListener('value-changed', (e) => {
68
+ this.value = e.detail.value;
69
+ });
70
+
71
+ this._textField = field;
72
+ },
73
+ });
74
+ this.addController(this._filterController);
75
+ }
76
+
77
+ /** @private */
78
+ _filterChanged(path, value, textField) {
79
+ if (path === undefined || value === undefined || !textField) {
80
+ return;
81
+ }
82
+ if (this._previousValue === undefined && value === '') {
83
+ return;
84
+ }
85
+
86
+ textField.value = value;
87
+ this._previousValue = value;
88
+
89
+ this._debouncerFilterChanged = Debouncer.debounce(this._debouncerFilterChanged, timeOut.after(200), () => {
90
+ this.dispatchEvent(new CustomEvent('filter-changed', { bubbles: true }));
91
+ });
92
+ }
93
+
94
+ focus() {
95
+ if (this._textField) {
96
+ this._textField.focus();
97
+ }
98
+ }
99
+ };