@vaadin/component-base 24.4.0-dev.b3e1d14600 → 24.4.0-rc2
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 +2 -2
- package/src/browser-utils.js +1 -1
- package/src/controller-mixin.d.ts +1 -1
- package/src/controller-mixin.js +1 -1
- package/src/data-provider-controller/cache.d.ts +1 -1
- package/src/data-provider-controller/cache.js +9 -53
- package/src/data-provider-controller/data-provider-controller.d.ts +1 -1
- package/src/data-provider-controller/data-provider-controller.js +4 -28
- package/src/data-provider-controller/helpers.d.ts +1 -1
- package/src/data-provider-controller/helpers.js +1 -1
- package/src/define.d.ts +1 -1
- package/src/define.js +2 -2
- package/src/delegate-state-mixin.d.ts +1 -1
- package/src/delegate-state-mixin.js +1 -1
- package/src/dir-mixin.d.ts +1 -1
- package/src/dir-mixin.js +1 -1
- package/src/dir-utils.d.ts +1 -1
- package/src/dir-utils.js +1 -1
- package/src/dom-utils.d.ts +1 -1
- package/src/dom-utils.js +1 -1
- package/src/element-mixin.d.ts +1 -1
- package/src/element-mixin.js +1 -1
- package/src/media-query-controller.d.ts +1 -1
- package/src/media-query-controller.js +1 -1
- package/src/overflow-controller.d.ts +1 -1
- package/src/overflow-controller.js +1 -1
- package/src/overlay-class-mixin.d.ts +1 -1
- package/src/overlay-class-mixin.js +2 -2
- package/src/path-utils.d.ts +1 -1
- package/src/path-utils.js +1 -1
- package/src/polylit-mixin.d.ts +1 -1
- package/src/polylit-mixin.js +24 -1
- package/src/resize-mixin.d.ts +1 -1
- package/src/resize-mixin.js +1 -1
- package/src/slot-child-observe-controller.d.ts +1 -1
- package/src/slot-child-observe-controller.js +1 -1
- package/src/slot-controller.d.ts +1 -1
- package/src/slot-controller.js +2 -2
- package/src/slot-observer.d.ts +1 -1
- package/src/slot-observer.js +1 -1
- package/src/slot-styles-mixin.d.ts +1 -1
- package/src/slot-styles-mixin.js +1 -1
- package/src/templates.js +1 -1
- package/src/tooltip-controller.d.ts +1 -1
- package/src/tooltip-controller.js +1 -1
- package/src/unique-id-utils.d.ts +1 -1
- package/src/unique-id-utils.js +1 -1
- package/src/url-utils.d.ts +8 -4
- package/src/url-utils.js +31 -9
- package/src/virtualizer-iron-list-adapter.js +124 -35
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/component-base",
|
|
3
|
-
"version": "24.4.0-
|
|
3
|
+
"version": "24.4.0-rc2",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -42,5 +42,5 @@
|
|
|
42
42
|
"@vaadin/testing-helpers": "^0.6.0",
|
|
43
43
|
"sinon": "^13.0.2"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "ea3d99e8cf67a337e959d5cab849f80464c7c7e5"
|
|
46
46
|
}
|
package/src/browser-utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2024 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';
|
package/src/controller-mixin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2024 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 { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2024 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 { DataProviderCallback } from './data-provider-controller.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2024 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 { getFlatIndexContext } from './helpers.js';
|
|
@@ -16,6 +16,13 @@ export class Cache {
|
|
|
16
16
|
*/
|
|
17
17
|
context;
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* The number of items.
|
|
21
|
+
*
|
|
22
|
+
* @type {number}
|
|
23
|
+
*/
|
|
24
|
+
size = 0;
|
|
25
|
+
|
|
19
26
|
/**
|
|
20
27
|
* The number of items to display per page.
|
|
21
28
|
*
|
|
@@ -51,14 +58,6 @@ export class Cache {
|
|
|
51
58
|
*/
|
|
52
59
|
__subCacheByIndex = {};
|
|
53
60
|
|
|
54
|
-
/**
|
|
55
|
-
* The number of items.
|
|
56
|
-
*
|
|
57
|
-
* @type {number}
|
|
58
|
-
* @private
|
|
59
|
-
*/
|
|
60
|
-
__size = 0;
|
|
61
|
-
|
|
62
61
|
/**
|
|
63
62
|
* The total number of items, including items from expanded sub-caches.
|
|
64
63
|
*
|
|
@@ -137,46 +136,6 @@ export class Cache {
|
|
|
137
136
|
return this.flatSize;
|
|
138
137
|
}
|
|
139
138
|
|
|
140
|
-
/**
|
|
141
|
-
* The number of items.
|
|
142
|
-
*
|
|
143
|
-
* @type {number}
|
|
144
|
-
* @private
|
|
145
|
-
*/
|
|
146
|
-
get size() {
|
|
147
|
-
return this.__size;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Sets the number of items.
|
|
152
|
-
*
|
|
153
|
-
* @type {number}
|
|
154
|
-
* @private
|
|
155
|
-
*/
|
|
156
|
-
set size(size) {
|
|
157
|
-
const oldSize = this.__size;
|
|
158
|
-
if (oldSize === size) {
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
this.__size = size;
|
|
163
|
-
|
|
164
|
-
if (this.context.placeholder !== undefined) {
|
|
165
|
-
this.items.length = size;
|
|
166
|
-
for (let i = 0; i < size; i++) {
|
|
167
|
-
// eslint-disable-next-line logical-assignment-operators
|
|
168
|
-
this.items[i] = this.items[i] || this.context.placeholder;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
Object.keys(this.pendingRequests).forEach((page) => {
|
|
173
|
-
const startIndex = parseInt(page) * this.pageSize;
|
|
174
|
-
if (startIndex >= this.size) {
|
|
175
|
-
delete this.pendingRequests[page];
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
|
|
180
139
|
/**
|
|
181
140
|
* Recalculates the flattened size for the cache and its descendant caches recursively.
|
|
182
141
|
*/
|
|
@@ -201,10 +160,7 @@ export class Cache {
|
|
|
201
160
|
setPage(page, items) {
|
|
202
161
|
const startIndex = page * this.pageSize;
|
|
203
162
|
items.forEach((item, i) => {
|
|
204
|
-
|
|
205
|
-
if (itemIndex < this.size) {
|
|
206
|
-
this.items[itemIndex] = item;
|
|
207
|
-
}
|
|
163
|
+
this.items[startIndex + i] = item;
|
|
208
164
|
});
|
|
209
165
|
}
|
|
210
166
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2024 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 { Cache } from './cache.js';
|
|
@@ -65,27 +65,12 @@ export class DataProviderController extends EventTarget {
|
|
|
65
65
|
*/
|
|
66
66
|
rootCache;
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
* Indicates whether any data has been loaded since the last cache clear.
|
|
70
|
-
*
|
|
71
|
-
* @type {boolean}
|
|
72
|
-
*/
|
|
73
|
-
hasData = false;
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* A placeholder item that is used to indicate that the item is not loaded yet.
|
|
77
|
-
*
|
|
78
|
-
* @type {undefined | object}
|
|
79
|
-
*/
|
|
80
|
-
placeholder;
|
|
81
|
-
|
|
82
|
-
constructor(host, { size, pageSize, isExpanded, getItemId, placeholder, dataProvider, dataProviderParams }) {
|
|
68
|
+
constructor(host, { size, pageSize, isExpanded, getItemId, dataProvider, dataProviderParams }) {
|
|
83
69
|
super();
|
|
84
70
|
this.host = host;
|
|
85
71
|
this.pageSize = pageSize;
|
|
86
72
|
this.getItemId = getItemId;
|
|
87
73
|
this.isExpanded = isExpanded;
|
|
88
|
-
this.placeholder = placeholder;
|
|
89
74
|
this.dataProvider = dataProvider;
|
|
90
75
|
this.dataProviderParams = dataProviderParams;
|
|
91
76
|
this.rootCache = this.__createRootCache(size);
|
|
@@ -102,7 +87,6 @@ export class DataProviderController extends EventTarget {
|
|
|
102
87
|
get __cacheContext() {
|
|
103
88
|
return {
|
|
104
89
|
isExpanded: this.isExpanded,
|
|
105
|
-
placeholder: this.placeholder,
|
|
106
90
|
// The controller instance is needed to ensure deprecated cache methods work.
|
|
107
91
|
__controller: this,
|
|
108
92
|
};
|
|
@@ -149,7 +133,6 @@ export class DataProviderController extends EventTarget {
|
|
|
149
133
|
*/
|
|
150
134
|
clearCache() {
|
|
151
135
|
this.rootCache = this.__createRootCache(this.rootCache.size);
|
|
152
|
-
this.hasData = false;
|
|
153
136
|
}
|
|
154
137
|
|
|
155
138
|
/**
|
|
@@ -204,7 +187,7 @@ export class DataProviderController extends EventTarget {
|
|
|
204
187
|
ensureFlatIndexLoaded(flatIndex) {
|
|
205
188
|
const { cache, page, item } = this.getFlatIndexContext(flatIndex);
|
|
206
189
|
|
|
207
|
-
if (
|
|
190
|
+
if (!item) {
|
|
208
191
|
this.__loadCachePage(cache, page);
|
|
209
192
|
}
|
|
210
193
|
}
|
|
@@ -219,7 +202,7 @@ export class DataProviderController extends EventTarget {
|
|
|
219
202
|
ensureFlatIndexHierarchy(flatIndex) {
|
|
220
203
|
const { cache, item, index } = this.getFlatIndexContext(flatIndex);
|
|
221
204
|
|
|
222
|
-
if (
|
|
205
|
+
if (item && this.isExpanded(item) && !cache.getSubCache(index)) {
|
|
223
206
|
const subCache = cache.createSubCache(index);
|
|
224
207
|
this.__loadCachePage(subCache, 0);
|
|
225
208
|
}
|
|
@@ -268,8 +251,6 @@ export class DataProviderController extends EventTarget {
|
|
|
268
251
|
|
|
269
252
|
this.recalculateFlatSize();
|
|
270
253
|
|
|
271
|
-
this.hasData = true;
|
|
272
|
-
|
|
273
254
|
this.dispatchEvent(new CustomEvent('page-received'));
|
|
274
255
|
|
|
275
256
|
delete cache.pendingRequests[page];
|
|
@@ -283,9 +264,4 @@ export class DataProviderController extends EventTarget {
|
|
|
283
264
|
|
|
284
265
|
this.dataProvider(params, callback);
|
|
285
266
|
}
|
|
286
|
-
|
|
287
|
-
/** @private */
|
|
288
|
-
__isPlaceholder(item) {
|
|
289
|
-
return item === this.placeholder;
|
|
290
|
-
}
|
|
291
267
|
}
|
package/src/define.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2024 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
6
|
export interface CustomElementType extends CustomElementConstructor {
|
package/src/define.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2024 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -9,7 +9,7 @@ export function defineCustomElement(CustomElement) {
|
|
|
9
9
|
if (!defined) {
|
|
10
10
|
Object.defineProperty(CustomElement, 'version', {
|
|
11
11
|
get() {
|
|
12
|
-
return '24.4.0-
|
|
12
|
+
return '24.4.0-rc2';
|
|
13
13
|
},
|
|
14
14
|
});
|
|
15
15
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2024 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) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2024 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 { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
|
package/src/dir-mixin.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2024 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';
|
package/src/dir-mixin.js
CHANGED
package/src/dir-utils.d.ts
CHANGED
package/src/dir-utils.js
CHANGED
package/src/dom-utils.d.ts
CHANGED
package/src/dom-utils.js
CHANGED
package/src/element-mixin.d.ts
CHANGED
package/src/element-mixin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2024 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 { setCancelSyntheticClickEvents } from '@polymer/polymer/lib/utils/settings.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2023 Vaadin Ltd.
|
|
3
|
+
* Copyright (c) 2023 - 2024 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -69,7 +69,7 @@ export const OverlayClassMixin = (superclass) =>
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
// Add new classes based on the overlayClass
|
|
72
|
-
const classesToAdd = typeof overlayClass === 'string' ? overlayClass.split(' ') : [];
|
|
72
|
+
const classesToAdd = typeof overlayClass === 'string' ? overlayClass.split(' ').filter(Boolean) : [];
|
|
73
73
|
if (classesToAdd.length > 0) {
|
|
74
74
|
classList.add(...classesToAdd);
|
|
75
75
|
}
|
package/src/path-utils.d.ts
CHANGED
package/src/path-utils.js
CHANGED
package/src/polylit-mixin.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2024 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';
|
package/src/polylit-mixin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2024 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 { dedupeMixin } from '@open-wc/dedupe-mixin';
|
|
@@ -93,6 +93,9 @@ const PolylitMixinImplementation = (superclass) => {
|
|
|
93
93
|
|
|
94
94
|
let result = defaultDescriptor;
|
|
95
95
|
|
|
96
|
+
// Set the key for this property
|
|
97
|
+
this.getOrCreateMap('__propKeys').set(name, key);
|
|
98
|
+
|
|
96
99
|
if (options.sync) {
|
|
97
100
|
result = {
|
|
98
101
|
get: defaultDescriptor.get,
|
|
@@ -232,6 +235,26 @@ const PolylitMixinImplementation = (superclass) => {
|
|
|
232
235
|
}
|
|
233
236
|
}
|
|
234
237
|
|
|
238
|
+
/**
|
|
239
|
+
* Set several properties at once and perform synchronous update.
|
|
240
|
+
* @protected
|
|
241
|
+
*/
|
|
242
|
+
setProperties(props) {
|
|
243
|
+
Object.entries(props).forEach(([name, value]) => {
|
|
244
|
+
// Use private key and not setter to not trigger
|
|
245
|
+
// update for properties marked as `sync: true`.
|
|
246
|
+
const key = this.constructor.__propKeys.get(name);
|
|
247
|
+
const oldValue = this[key];
|
|
248
|
+
this[key] = value;
|
|
249
|
+
this.requestUpdate(name, oldValue);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
// Perform sync update
|
|
253
|
+
if (this.hasUpdated) {
|
|
254
|
+
this.performUpdate();
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
235
258
|
/** @protected */
|
|
236
259
|
_createMethodObserver(observer) {
|
|
237
260
|
const dynamicObservers = getOrCreateMap(this, '__dynamicObservers');
|
package/src/resize-mixin.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2024 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';
|
package/src/resize-mixin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2024 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 { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
|
package/src/slot-controller.d.ts
CHANGED
package/src/slot-controller.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2024 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 { isEmptyTextNode } from './dom-utils.js';
|
|
@@ -111,12 +111,12 @@ export class SlotController extends EventTarget {
|
|
|
111
111
|
if (slotName !== '') {
|
|
112
112
|
node.setAttribute('slot', slotName);
|
|
113
113
|
}
|
|
114
|
-
this.node = node;
|
|
115
114
|
this.defaultNode = node;
|
|
116
115
|
}
|
|
117
116
|
}
|
|
118
117
|
|
|
119
118
|
if (node) {
|
|
119
|
+
this.node = node;
|
|
120
120
|
host.appendChild(node);
|
|
121
121
|
}
|
|
122
122
|
|
package/src/slot-observer.d.ts
CHANGED
package/src/slot-observer.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2024 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';
|
package/src/slot-styles-mixin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2024 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 { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
|
package/src/templates.js
CHANGED
package/src/unique-id-utils.d.ts
CHANGED
package/src/unique-id-utils.js
CHANGED
package/src/url-utils.d.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2023 Vaadin Ltd.
|
|
3
|
+
* Copyright (c) 2023 - 2024 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* Checks if two paths match based on their origin, pathname, and query parameters.
|
|
9
|
+
*
|
|
10
|
+
* The function matches an actual URL against an expected URL to see if they share
|
|
11
|
+
* the same base origin (like https://example.com), the same path (like /path/to/page),
|
|
12
|
+
* and if the actual URL contains at least all the query parameters with the same values
|
|
13
|
+
* from the expected URL.
|
|
10
14
|
*/
|
|
11
|
-
export declare function matchPaths(
|
|
15
|
+
export declare function matchPaths(actual: string, expected: string): boolean;
|
package/src/url-utils.js
CHANGED
|
@@ -1,19 +1,41 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2023 Vaadin Ltd.
|
|
3
|
+
* Copyright (c) 2023 - 2024 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
* with the same
|
|
8
|
+
* Checks if one set of URL parameters contains all the parameters
|
|
9
|
+
* with the same values from another set.
|
|
10
10
|
*
|
|
11
|
-
* @param {
|
|
12
|
-
* @param {
|
|
11
|
+
* @param {URLSearchParams} actual
|
|
12
|
+
* @param {URLSearchParams} expected
|
|
13
13
|
*/
|
|
14
|
-
|
|
14
|
+
function containsQueryParams(actual, expected) {
|
|
15
|
+
return [...expected.entries()].every(([key, value]) => {
|
|
16
|
+
return actual.getAll(key).includes(value);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Checks if two paths match based on their origin, pathname, and query parameters.
|
|
22
|
+
*
|
|
23
|
+
* The function matches an actual URL against an expected URL to see if they share
|
|
24
|
+
* the same base origin (like https://example.com), the same path (like /path/to/page),
|
|
25
|
+
* and if the actual URL contains at least all the query parameters with the same values
|
|
26
|
+
* from the expected URL.
|
|
27
|
+
*
|
|
28
|
+
* @param {string} actual The actual URL to match.
|
|
29
|
+
* @param {string} expected The expected URL to match.
|
|
30
|
+
*/
|
|
31
|
+
export function matchPaths(actual, expected) {
|
|
15
32
|
const base = document.baseURI;
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
33
|
+
const actualUrl = new URL(actual, base);
|
|
34
|
+
const expectedUrl = new URL(expected, base);
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
actualUrl.origin === expectedUrl.origin &&
|
|
38
|
+
actualUrl.pathname === expectedUrl.pathname &&
|
|
39
|
+
containsQueryParams(actualUrl.searchParams, expectedUrl.searchParams)
|
|
40
|
+
);
|
|
19
41
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2024 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
6
|
/* eslint-disable @typescript-eslint/member-ordering */
|
|
7
7
|
// https://github.com/vaadin/eslint-config-vaadin/issues/33
|
|
8
|
-
import { animationFrame, timeOut } from './async.js';
|
|
8
|
+
import { animationFrame, microTask, timeOut } from './async.js';
|
|
9
9
|
import { isSafari } from './browser-utils.js';
|
|
10
10
|
import { Debouncer, flush } from './debounce.js';
|
|
11
11
|
import { ironList } from './iron-list-core.js';
|
|
@@ -55,6 +55,13 @@ export class IronListAdapter {
|
|
|
55
55
|
this._scrollLineHeight = this._getScrollLineHeight();
|
|
56
56
|
this.scrollTarget.addEventListener('wheel', (e) => this.__onWheel(e));
|
|
57
57
|
|
|
58
|
+
this.scrollTarget.addEventListener('virtualizer-element-focused', (e) => this.__onElementFocused(e));
|
|
59
|
+
this.elementsContainer.addEventListener('focusin', (e) => {
|
|
60
|
+
this.scrollTarget.dispatchEvent(
|
|
61
|
+
new CustomEvent('virtualizer-element-focused', { detail: { element: this.__getFocusedElement() } }),
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
|
|
58
65
|
if (this.reorderElements) {
|
|
59
66
|
// Reordering the physical elements cancels the user's grab of the scroll bar handle on Safari.
|
|
60
67
|
// Need to defer reordering until the user lets go of the scroll bar handle.
|
|
@@ -82,6 +89,10 @@ export class IronListAdapter {
|
|
|
82
89
|
return this.lastVisibleIndex + this._vidxOffset;
|
|
83
90
|
}
|
|
84
91
|
|
|
92
|
+
get _maxVirtualIndexOffset() {
|
|
93
|
+
return this.size - this._virtualCount;
|
|
94
|
+
}
|
|
95
|
+
|
|
85
96
|
__hasPlaceholders() {
|
|
86
97
|
return this.__getVisibleElements().some((el) => el.__virtualizerPlaceholder);
|
|
87
98
|
}
|
|
@@ -106,7 +117,7 @@ export class IronListAdapter {
|
|
|
106
117
|
let targetVirtualIndex = Math.floor((index / this.size) * this._virtualCount);
|
|
107
118
|
if (this._virtualCount - targetVirtualIndex < visibleElementCount) {
|
|
108
119
|
targetVirtualIndex = this._virtualCount - (this.size - index);
|
|
109
|
-
this._vidxOffset = this.
|
|
120
|
+
this._vidxOffset = this._maxVirtualIndexOffset;
|
|
110
121
|
} else if (targetVirtualIndex < visibleElementCount) {
|
|
111
122
|
if (index < OFFSET_ADJUST_MIN_THRESHOLD) {
|
|
112
123
|
targetVirtualIndex = index;
|
|
@@ -136,7 +147,6 @@ export class IronListAdapter {
|
|
|
136
147
|
}
|
|
137
148
|
|
|
138
149
|
flush() {
|
|
139
|
-
const startPhysicalCount = this._physicalCount;
|
|
140
150
|
// The scroll target is hidden.
|
|
141
151
|
if (this.scrollTarget.offsetHeight === 0) {
|
|
142
152
|
return;
|
|
@@ -154,11 +164,6 @@ export class IronListAdapter {
|
|
|
154
164
|
if (this.__debouncerWheelAnimationFrame) {
|
|
155
165
|
this.__debouncerWheelAnimationFrame.flush();
|
|
156
166
|
}
|
|
157
|
-
|
|
158
|
-
if (this._physicalCount !== startPhysicalCount) {
|
|
159
|
-
// Flushing again until physical count stabilizes fixes https://github.com/vaadin/flow-components/issues/5595#issuecomment-1770278913
|
|
160
|
-
this.flush();
|
|
161
|
-
}
|
|
162
167
|
}
|
|
163
168
|
|
|
164
169
|
update(startIndex = 0, endIndex = this.size - 1) {
|
|
@@ -227,6 +232,7 @@ export class IronListAdapter {
|
|
|
227
232
|
// Clean up temporary placeholder sizing
|
|
228
233
|
if (el.__virtualizerPlaceholder) {
|
|
229
234
|
el.style.paddingTop = '';
|
|
235
|
+
el.style.opacity = '';
|
|
230
236
|
el.__virtualizerPlaceholder = false;
|
|
231
237
|
}
|
|
232
238
|
|
|
@@ -251,6 +257,7 @@ export class IronListAdapter {
|
|
|
251
257
|
// Assign a temporary placeholder sizing to elements that would otherwise end up having
|
|
252
258
|
// no height.
|
|
253
259
|
el.style.paddingTop = `${this.__placeholderHeight}px`;
|
|
260
|
+
el.style.opacity = '0';
|
|
254
261
|
el.__virtualizerPlaceholder = true;
|
|
255
262
|
|
|
256
263
|
// Manually schedule the resize handler to make sure the placeholder padding is
|
|
@@ -297,24 +304,41 @@ export class IronListAdapter {
|
|
|
297
304
|
this._debouncers._increasePoolIfNeeded.cancel();
|
|
298
305
|
}
|
|
299
306
|
|
|
307
|
+
// Prevent element update while the scroll position is being restored
|
|
308
|
+
this.__preventElementUpdates = true;
|
|
309
|
+
|
|
310
|
+
// Record the scroll position before changing the size
|
|
311
|
+
let fvi; // First visible index
|
|
312
|
+
let fviOffsetBefore; // Scroll offset of the first visible index
|
|
313
|
+
if (size > 0) {
|
|
314
|
+
fvi = this.adjustedFirstVisibleIndex;
|
|
315
|
+
fviOffsetBefore = this.__getIndexScrollOffset(fvi);
|
|
316
|
+
}
|
|
317
|
+
|
|
300
318
|
// Change the size
|
|
301
319
|
this.__size = size;
|
|
302
320
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
//
|
|
313
|
-
|
|
314
|
-
this.
|
|
315
|
-
|
|
321
|
+
this._itemsChanged({
|
|
322
|
+
path: 'items',
|
|
323
|
+
});
|
|
324
|
+
flush();
|
|
325
|
+
|
|
326
|
+
// Try to restore the scroll position if the new size is larger than 0
|
|
327
|
+
if (size > 0) {
|
|
328
|
+
fvi = Math.min(fvi, size - 1);
|
|
329
|
+
// Note, calling scrollToIndex also updates the virtual index offset,
|
|
330
|
+
// causing the virtualizer to add more items when size is increased,
|
|
331
|
+
// and remove exceeding items when size is decreased.
|
|
332
|
+
this.scrollToIndex(fvi);
|
|
333
|
+
|
|
334
|
+
const fviOffsetAfter = this.__getIndexScrollOffset(fvi);
|
|
335
|
+
if (fviOffsetBefore !== undefined && fviOffsetAfter !== undefined) {
|
|
336
|
+
this._scrollTop += fviOffsetBefore - fviOffsetAfter;
|
|
337
|
+
}
|
|
316
338
|
}
|
|
317
339
|
|
|
340
|
+
this.__preventElementUpdates = false;
|
|
341
|
+
|
|
318
342
|
// When reducing size while invisible, iron-list does not update items, so
|
|
319
343
|
// their hidden state is not updated and their __lastUpdatedIndex is not
|
|
320
344
|
// reset. In that case force an update here.
|
|
@@ -326,10 +350,12 @@ export class IronListAdapter {
|
|
|
326
350
|
requestAnimationFrame(() => this._resizeHandler());
|
|
327
351
|
}
|
|
328
352
|
|
|
329
|
-
// Schedule and flush a resize handler
|
|
330
|
-
// re-render for the elements.
|
|
353
|
+
// Schedule and flush a resize handler
|
|
331
354
|
this._resizeHandler();
|
|
332
355
|
flush();
|
|
356
|
+
// Schedule an update to ensure item positions are correct after subsequent size changes
|
|
357
|
+
// Fix for https://github.com/vaadin/flow-components/issues/6269
|
|
358
|
+
this._debounce('_update', this._update, microTask);
|
|
333
359
|
}
|
|
334
360
|
|
|
335
361
|
/** @private */
|
|
@@ -425,6 +451,75 @@ export class IronListAdapter {
|
|
|
425
451
|
/** @private */
|
|
426
452
|
toggleScrollListener() {}
|
|
427
453
|
|
|
454
|
+
/** @private */
|
|
455
|
+
__getFocusedElement(visibleElements = this.__getVisibleElements()) {
|
|
456
|
+
return visibleElements.find(
|
|
457
|
+
(element) =>
|
|
458
|
+
element.contains(this.elementsContainer.getRootNode().activeElement) ||
|
|
459
|
+
element.contains(this.scrollTarget.getRootNode().activeElement),
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/** @private */
|
|
464
|
+
__nextFocusableSiblingMissing(focusedElement, visibleElements) {
|
|
465
|
+
return (
|
|
466
|
+
// Check if focused element is the last visible DOM element
|
|
467
|
+
visibleElements.indexOf(focusedElement) === visibleElements.length - 1 &&
|
|
468
|
+
// ...while there are more items available
|
|
469
|
+
this.size > focusedElement.__virtualIndex + 1
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/** @private */
|
|
474
|
+
__previousFocusableSiblingMissing(focusedElement, visibleElements) {
|
|
475
|
+
return (
|
|
476
|
+
// Check if focused element is the first visible DOM element
|
|
477
|
+
visibleElements.indexOf(focusedElement) === 0 &&
|
|
478
|
+
// ...while there are preceding items available
|
|
479
|
+
focusedElement.__virtualIndex > 0
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/** @private */
|
|
484
|
+
__onElementFocused(e) {
|
|
485
|
+
if (!this.reorderElements) {
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
const focusedElement = e.detail.element;
|
|
490
|
+
if (!focusedElement) {
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// User has tabbed to or within a virtualizer element.
|
|
495
|
+
// Check if a next or previous focusable sibling is missing while it should be there (so the user can continue tabbing).
|
|
496
|
+
// The focusable sibling might be missing due to the elements not yet being in the correct DOM order.
|
|
497
|
+
// First try flushing (which also flushes any active __scrollReorderDebouncer).
|
|
498
|
+
const visibleElements = this.__getVisibleElements();
|
|
499
|
+
if (
|
|
500
|
+
this.__previousFocusableSiblingMissing(focusedElement, visibleElements) ||
|
|
501
|
+
this.__nextFocusableSiblingMissing(focusedElement, visibleElements)
|
|
502
|
+
) {
|
|
503
|
+
this.flush();
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// If the focusable sibling is still missing (because the focused element is at the edge of the viewport and
|
|
507
|
+
// the virtual scrolling logic hasn't had the need to recycle elements), scroll the virtualizer just enough to
|
|
508
|
+
// have the focusable sibling inside the visible viewport to force the virtualizer to recycle.
|
|
509
|
+
const reorderedVisibleElements = this.__getVisibleElements();
|
|
510
|
+
if (this.__nextFocusableSiblingMissing(focusedElement, reorderedVisibleElements)) {
|
|
511
|
+
this._scrollTop +=
|
|
512
|
+
Math.ceil(focusedElement.getBoundingClientRect().bottom) -
|
|
513
|
+
Math.floor(this.scrollTarget.getBoundingClientRect().bottom - 1);
|
|
514
|
+
this.flush();
|
|
515
|
+
} else if (this.__previousFocusableSiblingMissing(focusedElement, reorderedVisibleElements)) {
|
|
516
|
+
this._scrollTop -=
|
|
517
|
+
Math.ceil(this.scrollTarget.getBoundingClientRect().top + 1) -
|
|
518
|
+
Math.floor(focusedElement.getBoundingClientRect().top);
|
|
519
|
+
this.flush();
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
428
523
|
_scrollHandler() {
|
|
429
524
|
// The scroll target is hidden.
|
|
430
525
|
if (this.scrollTarget.offsetHeight === 0) {
|
|
@@ -662,13 +757,7 @@ export class IronListAdapter {
|
|
|
662
757
|
|
|
663
758
|
// Which row to use as a target?
|
|
664
759
|
const visibleElements = this.__getVisibleElements();
|
|
665
|
-
|
|
666
|
-
const elementWithFocus = visibleElements.find(
|
|
667
|
-
(element) =>
|
|
668
|
-
element.contains(this.elementsContainer.getRootNode().activeElement) ||
|
|
669
|
-
element.contains(this.scrollTarget.getRootNode().activeElement),
|
|
670
|
-
);
|
|
671
|
-
const targetElement = elementWithFocus || visibleElements[0];
|
|
760
|
+
const targetElement = this.__getFocusedElement(visibleElements) || visibleElements[0];
|
|
672
761
|
if (!targetElement) {
|
|
673
762
|
// All elements are hidden, don't reorder
|
|
674
763
|
return;
|
|
@@ -703,15 +792,16 @@ export class IronListAdapter {
|
|
|
703
792
|
|
|
704
793
|
/** @private */
|
|
705
794
|
_adjustVirtualIndexOffset(delta) {
|
|
795
|
+
const maxOffset = this._maxVirtualIndexOffset;
|
|
796
|
+
|
|
706
797
|
if (this._virtualCount >= this.size) {
|
|
707
798
|
this._vidxOffset = 0;
|
|
708
799
|
} else if (this.__skipNextVirtualIndexAdjust) {
|
|
709
800
|
this.__skipNextVirtualIndexAdjust = false;
|
|
710
801
|
} else if (Math.abs(delta) > 10000) {
|
|
711
802
|
// Process a large scroll position change
|
|
712
|
-
const scale = this._scrollTop / (this.scrollTarget.scrollHeight - this.scrollTarget.
|
|
713
|
-
|
|
714
|
-
this._vidxOffset = Math.round(offset - scale * this._virtualCount);
|
|
803
|
+
const scale = this._scrollTop / (this.scrollTarget.scrollHeight - this.scrollTarget.clientHeight);
|
|
804
|
+
this._vidxOffset = Math.round(scale * maxOffset);
|
|
715
805
|
} else {
|
|
716
806
|
// Make sure user can always swipe/wheel scroll to the start and end
|
|
717
807
|
const oldOffset = this._vidxOffset;
|
|
@@ -730,7 +820,6 @@ export class IronListAdapter {
|
|
|
730
820
|
}
|
|
731
821
|
|
|
732
822
|
// Near end
|
|
733
|
-
const maxOffset = this.size - this._virtualCount;
|
|
734
823
|
if (this._scrollTop >= this._maxScrollTop && this._maxScrollTop > 0) {
|
|
735
824
|
this._vidxOffset = maxOffset;
|
|
736
825
|
if (oldOffset !== this._vidxOffset) {
|