@vaadin/component-base 24.5.0-alpha1 → 24.5.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.
- package/README.md +1 -1
- package/package.json +5 -5
- package/src/browser-utils.js +1 -1
- package/src/data-provider-controller/cache.js +50 -9
- package/src/data-provider-controller/data-provider-controller.d.ts +12 -5
- package/src/data-provider-controller/data-provider-controller.js +33 -10
- package/src/define.js +1 -1
- package/src/gestures.js +2 -2
- package/src/overflow-controller.js +1 -1
- package/src/slot-controller.d.ts +1 -0
- package/src/slot-controller.js +3 -4
- package/src/url-utils.js +8 -6
- package/src/virtualizer-iron-list-adapter.js +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ A set of helpers and mixins used by Vaadin components.
|
|
|
4
4
|
|
|
5
5
|
## Contributing
|
|
6
6
|
|
|
7
|
-
Read the [contributing guide](https://vaadin.com/docs/latest/contributing
|
|
7
|
+
Read the [contributing guide](https://vaadin.com/docs/latest/contributing) to learn about our development process, how to propose bugfixes and improvements, and how to test your changes to Vaadin components.
|
|
8
8
|
|
|
9
9
|
## License
|
|
10
10
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/component-base",
|
|
3
|
-
"version": "24.5.0-
|
|
3
|
+
"version": "24.5.0-alpha10",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
"lit": "^3.0.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@
|
|
42
|
-
"@vaadin/testing-helpers": "^0.
|
|
43
|
-
"sinon": "^
|
|
41
|
+
"@vaadin/chai-plugins": "24.5.0-alpha10",
|
|
42
|
+
"@vaadin/testing-helpers": "^1.0.0",
|
|
43
|
+
"sinon": "^18.0.0"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "6f9c37308031af872a98017bfab4de89aeacda51"
|
|
46
46
|
}
|
package/src/browser-utils.js
CHANGED
|
@@ -16,13 +16,6 @@ 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
|
-
|
|
26
19
|
/**
|
|
27
20
|
* The number of items to display per page.
|
|
28
21
|
*
|
|
@@ -58,6 +51,14 @@ export class Cache {
|
|
|
58
51
|
*/
|
|
59
52
|
__subCacheByIndex = {};
|
|
60
53
|
|
|
54
|
+
/**
|
|
55
|
+
* The number of items.
|
|
56
|
+
*
|
|
57
|
+
* @type {number}
|
|
58
|
+
* @private
|
|
59
|
+
*/
|
|
60
|
+
__size = 0;
|
|
61
|
+
|
|
61
62
|
/**
|
|
62
63
|
* The total number of items, including items from expanded sub-caches.
|
|
63
64
|
*
|
|
@@ -76,7 +77,7 @@ export class Cache {
|
|
|
76
77
|
constructor(context, pageSize, size, parentCache, parentCacheIndex) {
|
|
77
78
|
this.context = context;
|
|
78
79
|
this.pageSize = pageSize;
|
|
79
|
-
this.size = size
|
|
80
|
+
this.size = size;
|
|
80
81
|
this.parentCache = parentCache;
|
|
81
82
|
this.parentCacheIndex = parentCacheIndex;
|
|
82
83
|
this.__flatSize = size || 0;
|
|
@@ -136,6 +137,43 @@ export class Cache {
|
|
|
136
137
|
return this.flatSize;
|
|
137
138
|
}
|
|
138
139
|
|
|
140
|
+
/**
|
|
141
|
+
* The number of items.
|
|
142
|
+
*
|
|
143
|
+
* @return {number}
|
|
144
|
+
*/
|
|
145
|
+
get size() {
|
|
146
|
+
return this.__size;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Sets the number of items.
|
|
151
|
+
*
|
|
152
|
+
* @param {number} size
|
|
153
|
+
*/
|
|
154
|
+
set size(size) {
|
|
155
|
+
const oldSize = this.__size;
|
|
156
|
+
if (oldSize === size) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
this.__size = size;
|
|
161
|
+
|
|
162
|
+
if (this.context.placeholder !== undefined) {
|
|
163
|
+
this.items.length = size || 0;
|
|
164
|
+
for (let i = 0; i < size || 0; i++) {
|
|
165
|
+
this.items[i] ||= this.context.placeholder;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
Object.keys(this.pendingRequests).forEach((page) => {
|
|
170
|
+
const startIndex = parseInt(page) * this.pageSize;
|
|
171
|
+
if (startIndex >= this.size || 0) {
|
|
172
|
+
delete this.pendingRequests[page];
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
139
177
|
/**
|
|
140
178
|
* Recalculates the flattened size for the cache and its descendant caches recursively.
|
|
141
179
|
*/
|
|
@@ -160,7 +198,10 @@ export class Cache {
|
|
|
160
198
|
setPage(page, items) {
|
|
161
199
|
const startIndex = page * this.pageSize;
|
|
162
200
|
items.forEach((item, i) => {
|
|
163
|
-
|
|
201
|
+
const itemIndex = startIndex + i;
|
|
202
|
+
if (this.size === undefined || itemIndex < this.size) {
|
|
203
|
+
this.items[itemIndex] = item;
|
|
204
|
+
}
|
|
164
205
|
});
|
|
165
206
|
}
|
|
166
207
|
|
|
@@ -43,11 +43,6 @@ export class DataProviderController<TItem, TDataProviderParams extends Record<st
|
|
|
43
43
|
*/
|
|
44
44
|
dataProviderParams: () => TDataProviderParams;
|
|
45
45
|
|
|
46
|
-
/**
|
|
47
|
-
* A number of items in the root cache.
|
|
48
|
-
*/
|
|
49
|
-
size?: number;
|
|
50
|
-
|
|
51
46
|
/**
|
|
52
47
|
* A number of items to display per page.
|
|
53
48
|
*/
|
|
@@ -69,11 +64,23 @@ export class DataProviderController<TItem, TDataProviderParams extends Record<st
|
|
|
69
64
|
*/
|
|
70
65
|
rootCache: Cache<TItem>;
|
|
71
66
|
|
|
67
|
+
/**
|
|
68
|
+
* A placeholder item that is used to indicate that the item is not loaded yet.
|
|
69
|
+
*/
|
|
70
|
+
placeholder?: unknown;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* A callback that returns whether the given item is a placeholder.
|
|
74
|
+
*/
|
|
75
|
+
isPlaceholder?: (item: unknown) => boolean;
|
|
76
|
+
|
|
72
77
|
constructor(
|
|
73
78
|
host: HTMLElement,
|
|
74
79
|
config: {
|
|
75
80
|
size?: number;
|
|
76
81
|
pageSize: number;
|
|
82
|
+
placeholder?: unknown;
|
|
83
|
+
isPlaceholder?(item: unknown): boolean;
|
|
77
84
|
getItemId(item: TItem): unknown;
|
|
78
85
|
isExpanded(item: TItem): boolean;
|
|
79
86
|
dataProvider: DataProvider<TItem, TDataProviderParams>;
|
|
@@ -29,13 +29,6 @@ export class DataProviderController extends EventTarget {
|
|
|
29
29
|
*/
|
|
30
30
|
dataProviderParams;
|
|
31
31
|
|
|
32
|
-
/**
|
|
33
|
-
* A number of items in the root cache.
|
|
34
|
-
*
|
|
35
|
-
* @type {number}
|
|
36
|
-
*/
|
|
37
|
-
size;
|
|
38
|
-
|
|
39
32
|
/**
|
|
40
33
|
* A number of items to display per page.
|
|
41
34
|
*
|
|
@@ -65,12 +58,31 @@ export class DataProviderController extends EventTarget {
|
|
|
65
58
|
*/
|
|
66
59
|
rootCache;
|
|
67
60
|
|
|
68
|
-
|
|
61
|
+
/**
|
|
62
|
+
* A placeholder item that is used to indicate that the item is not loaded yet.
|
|
63
|
+
*
|
|
64
|
+
* @type {unknown}
|
|
65
|
+
*/
|
|
66
|
+
placeholder;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* A callback that returns whether the given item is a placeholder.
|
|
70
|
+
*
|
|
71
|
+
* @type {(item: unknown) => boolean}
|
|
72
|
+
*/
|
|
73
|
+
isPlaceholder;
|
|
74
|
+
|
|
75
|
+
constructor(
|
|
76
|
+
host,
|
|
77
|
+
{ size, pageSize, isExpanded, getItemId, isPlaceholder, placeholder, dataProvider, dataProviderParams },
|
|
78
|
+
) {
|
|
69
79
|
super();
|
|
70
80
|
this.host = host;
|
|
71
81
|
this.pageSize = pageSize;
|
|
72
82
|
this.getItemId = getItemId;
|
|
73
83
|
this.isExpanded = isExpanded;
|
|
84
|
+
this.placeholder = placeholder;
|
|
85
|
+
this.isPlaceholder = isPlaceholder;
|
|
74
86
|
this.dataProvider = dataProvider;
|
|
75
87
|
this.dataProviderParams = dataProviderParams;
|
|
76
88
|
this.rootCache = this.__createRootCache(size);
|
|
@@ -87,6 +99,7 @@ export class DataProviderController extends EventTarget {
|
|
|
87
99
|
get __cacheContext() {
|
|
88
100
|
return {
|
|
89
101
|
isExpanded: this.isExpanded,
|
|
102
|
+
placeholder: this.placeholder,
|
|
90
103
|
// The controller instance is needed to ensure deprecated cache methods work.
|
|
91
104
|
__controller: this,
|
|
92
105
|
};
|
|
@@ -187,7 +200,7 @@ export class DataProviderController extends EventTarget {
|
|
|
187
200
|
ensureFlatIndexLoaded(flatIndex) {
|
|
188
201
|
const { cache, page, item } = this.getFlatIndexContext(flatIndex);
|
|
189
202
|
|
|
190
|
-
if (!item) {
|
|
203
|
+
if (!this.__isItemLoaded(item)) {
|
|
191
204
|
this.__loadCachePage(cache, page);
|
|
192
205
|
}
|
|
193
206
|
}
|
|
@@ -202,7 +215,7 @@ export class DataProviderController extends EventTarget {
|
|
|
202
215
|
ensureFlatIndexHierarchy(flatIndex) {
|
|
203
216
|
const { cache, item, index } = this.getFlatIndexContext(flatIndex);
|
|
204
217
|
|
|
205
|
-
if (item && this.isExpanded(item) && !cache.getSubCache(index)) {
|
|
218
|
+
if (this.__isItemLoaded(item) && this.isExpanded(item) && !cache.getSubCache(index)) {
|
|
206
219
|
const subCache = cache.createSubCache(index);
|
|
207
220
|
this.__loadCachePage(subCache, 0);
|
|
208
221
|
}
|
|
@@ -264,4 +277,14 @@ export class DataProviderController extends EventTarget {
|
|
|
264
277
|
|
|
265
278
|
this.dataProvider(params, callback);
|
|
266
279
|
}
|
|
280
|
+
|
|
281
|
+
/** @private */
|
|
282
|
+
__isItemLoaded(item) {
|
|
283
|
+
if (this.isPlaceholder) {
|
|
284
|
+
return !this.isPlaceholder(item);
|
|
285
|
+
} else if (this.placeholder) {
|
|
286
|
+
return item !== this.placeholder;
|
|
287
|
+
}
|
|
288
|
+
return !!item;
|
|
289
|
+
}
|
|
267
290
|
}
|
package/src/define.js
CHANGED
package/src/gestures.js
CHANGED
|
@@ -45,7 +45,7 @@ const MOUSE_WHICH_TO_BUTTONS = [0, 1, 4, 2];
|
|
|
45
45
|
const MOUSE_HAS_BUTTONS = (function () {
|
|
46
46
|
try {
|
|
47
47
|
return new MouseEvent('test', { buttons: 1 }).buttons === 1;
|
|
48
|
-
} catch (
|
|
48
|
+
} catch (_) {
|
|
49
49
|
return false;
|
|
50
50
|
}
|
|
51
51
|
})();
|
|
@@ -71,7 +71,7 @@ let supportsPassive = false;
|
|
|
71
71
|
});
|
|
72
72
|
window.addEventListener('test', null, opts);
|
|
73
73
|
window.removeEventListener('test', null, opts);
|
|
74
|
-
} catch (
|
|
74
|
+
} catch (_) {}
|
|
75
75
|
})();
|
|
76
76
|
|
|
77
77
|
/**
|
|
@@ -48,7 +48,7 @@ export class OverflowController {
|
|
|
48
48
|
observe() {
|
|
49
49
|
const { host } = this;
|
|
50
50
|
|
|
51
|
-
this.__resizeObserver = new ResizeObserver((
|
|
51
|
+
this.__resizeObserver = new ResizeObserver(() => {
|
|
52
52
|
this.__debounceOverflow = Debouncer.debounce(this.__debounceOverflow, animationFrame, () => {
|
|
53
53
|
this.__updateOverflow();
|
|
54
54
|
});
|
package/src/slot-controller.d.ts
CHANGED
package/src/slot-controller.js
CHANGED
|
@@ -19,15 +19,14 @@ export class SlotController extends EventTarget {
|
|
|
19
19
|
* @return {string}
|
|
20
20
|
* @protected
|
|
21
21
|
*/
|
|
22
|
-
static generateId(host,
|
|
23
|
-
const prefix = slotName || 'default';
|
|
22
|
+
static generateId(host, prefix = 'default') {
|
|
24
23
|
return `${prefix}-${host.localName}-${generateUniqueId()}`;
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
constructor(host, slotName, tagName, config = {}) {
|
|
28
27
|
super();
|
|
29
28
|
|
|
30
|
-
const { initializer, multiple, observe, useUniqueId } = config;
|
|
29
|
+
const { initializer, multiple, observe, useUniqueId, uniqueIdPrefix } = config;
|
|
31
30
|
|
|
32
31
|
this.host = host;
|
|
33
32
|
this.slotName = slotName;
|
|
@@ -42,7 +41,7 @@ export class SlotController extends EventTarget {
|
|
|
42
41
|
|
|
43
42
|
// Only generate the default ID if requested by the controller.
|
|
44
43
|
if (useUniqueId) {
|
|
45
|
-
this.defaultId = this.constructor.generateId(host, slotName);
|
|
44
|
+
this.defaultId = this.constructor.generateId(host, uniqueIdPrefix || slotName);
|
|
46
45
|
}
|
|
47
46
|
}
|
|
48
47
|
|
package/src/url-utils.js
CHANGED
|
@@ -27,15 +27,17 @@ function containsQueryParams(actual, expected) {
|
|
|
27
27
|
*
|
|
28
28
|
* @param {string} actual The actual URL to match.
|
|
29
29
|
* @param {string} expected The expected URL to match.
|
|
30
|
+
* @param {Object} matchOptions Options for path matching.
|
|
30
31
|
*/
|
|
31
|
-
export function matchPaths(actual, expected) {
|
|
32
|
+
export function matchPaths(actual, expected, matchOptions = { matchNested: false }) {
|
|
32
33
|
const base = document.baseURI;
|
|
33
34
|
const actualUrl = new URL(actual, base);
|
|
34
35
|
const expectedUrl = new URL(expected, base);
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
actualUrl.pathname === expectedUrl.pathname
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
const matchesOrigin = actualUrl.origin === expectedUrl.origin;
|
|
38
|
+
const matchesPath = matchOptions.matchNested
|
|
39
|
+
? actualUrl.pathname === expectedUrl.pathname || actualUrl.pathname.startsWith(`${expectedUrl.pathname}/`)
|
|
40
|
+
: actualUrl.pathname === expectedUrl.pathname;
|
|
41
|
+
|
|
42
|
+
return matchesOrigin && matchesPath && containsQueryParams(actualUrl.searchParams, expectedUrl.searchParams);
|
|
41
43
|
}
|
|
@@ -56,7 +56,7 @@ export class IronListAdapter {
|
|
|
56
56
|
this.scrollTarget.addEventListener('wheel', (e) => this.__onWheel(e));
|
|
57
57
|
|
|
58
58
|
this.scrollTarget.addEventListener('virtualizer-element-focused', (e) => this.__onElementFocused(e));
|
|
59
|
-
this.elementsContainer.addEventListener('focusin', (
|
|
59
|
+
this.elementsContainer.addEventListener('focusin', () => {
|
|
60
60
|
this.scrollTarget.dispatchEvent(
|
|
61
61
|
new CustomEvent('virtualizer-element-focused', { detail: { element: this.__getFocusedElement() } }),
|
|
62
62
|
);
|