@vaadin/component-base 24.2.0-dev.f254716fe → 24.3.0-alpha2
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/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +3 -3
- package/src/data-provider-controller/cache.d.ts +146 -0
- package/src/data-provider-controller/cache.js +136 -77
- package/src/data-provider-controller/data-provider-controller.d.ts +156 -0
- package/src/data-provider-controller/data-provider-controller.js +248 -0
- package/src/data-provider-controller/helpers.d.ts +32 -0
- package/src/data-provider-controller/helpers.js +16 -9
- package/src/define.d.ts +10 -0
- package/src/define.js +28 -0
- package/src/dom-utils.d.ts +7 -0
- package/src/dom-utils.js +21 -0
- package/src/element-mixin.d.ts +1 -0
- package/src/element-mixin.js +0 -4
- package/src/overflow-controller.js +23 -13
- package/src/path-utils.d.ts +15 -0
- package/src/path-utils.js +29 -0
- package/src/polylit-mixin.js +38 -16
- package/src/slot-controller.js +6 -6
- package/src/slot-observer.d.ts +34 -0
- package/src/slot-observer.js +105 -0
- package/src/slot-styles-mixin.d.ts +21 -0
- package/src/slot-styles-mixin.js +76 -0
- package/src/tooltip-controller.d.ts +13 -0
- package/src/tooltip-controller.js +36 -0
- package/src/virtualizer-iron-list-adapter.js +27 -1
- package/src/data-provider-controller.js +0 -126
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2023 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A helper for observing slot changes.
|
|
9
|
+
*/
|
|
10
|
+
export class SlotObserver {
|
|
11
|
+
constructor(
|
|
12
|
+
slot: HTMLSlotElement,
|
|
13
|
+
callback: (info: { addedNodes: Node[]; movedNodes: Node[]; removedNodes: Node[] }) => void,
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Activates an observer. This method is automatically called when
|
|
18
|
+
* a `SlotObserver` is created. It should only be called to re-activate
|
|
19
|
+
* an observer that has been deactivated via the `disconnect` method.
|
|
20
|
+
*/
|
|
21
|
+
connect(): void;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Deactivates the observer. After calling this method the observer callback
|
|
25
|
+
* will not be called when changes to slotted nodes occur. The `connect` method
|
|
26
|
+
* may be subsequently called to reactivate the observer.
|
|
27
|
+
*/
|
|
28
|
+
disconnect(): void;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Run the observer callback synchronously.
|
|
32
|
+
*/
|
|
33
|
+
flush(): void;
|
|
34
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2023 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A helper for observing slot changes.
|
|
9
|
+
*/
|
|
10
|
+
export class SlotObserver {
|
|
11
|
+
constructor(slot, callback) {
|
|
12
|
+
/** @type HTMLSlotElement */
|
|
13
|
+
this.slot = slot;
|
|
14
|
+
|
|
15
|
+
/** @type Function */
|
|
16
|
+
this.callback = callback;
|
|
17
|
+
|
|
18
|
+
/** @type {Node[]} */
|
|
19
|
+
this._storedNodes = [];
|
|
20
|
+
|
|
21
|
+
this._connected = false;
|
|
22
|
+
this._scheduled = false;
|
|
23
|
+
|
|
24
|
+
this._boundSchedule = () => {
|
|
25
|
+
this._schedule();
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
this.connect();
|
|
29
|
+
this._schedule();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Activates an observer. This method is automatically called when
|
|
34
|
+
* a `SlotObserver` is created. It should only be called to re-activate
|
|
35
|
+
* an observer that has been deactivated via the `disconnect` method.
|
|
36
|
+
*/
|
|
37
|
+
connect() {
|
|
38
|
+
this.slot.addEventListener('slotchange', this._boundSchedule);
|
|
39
|
+
this._connected = true;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Deactivates the observer. After calling this method the observer callback
|
|
44
|
+
* will not be called when changes to slotted nodes occur. The `connect` method
|
|
45
|
+
* may be subsequently called to reactivate the observer.
|
|
46
|
+
*/
|
|
47
|
+
disconnect() {
|
|
48
|
+
this.slot.removeEventListener('slotchange', this._boundSchedule);
|
|
49
|
+
this._connected = false;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** @private */
|
|
53
|
+
_schedule() {
|
|
54
|
+
if (!this._scheduled) {
|
|
55
|
+
this._scheduled = true;
|
|
56
|
+
|
|
57
|
+
queueMicrotask(() => {
|
|
58
|
+
this.flush();
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Run the observer callback synchronously.
|
|
65
|
+
*/
|
|
66
|
+
flush() {
|
|
67
|
+
if (!this._connected) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
this._scheduled = false;
|
|
72
|
+
|
|
73
|
+
this._processNodes();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** @private */
|
|
77
|
+
_processNodes() {
|
|
78
|
+
const currentNodes = this.slot.assignedNodes({ flatten: true });
|
|
79
|
+
|
|
80
|
+
let addedNodes = [];
|
|
81
|
+
const removedNodes = [];
|
|
82
|
+
const movedNodes = [];
|
|
83
|
+
|
|
84
|
+
if (currentNodes.length) {
|
|
85
|
+
addedNodes = currentNodes.filter((node) => !this._storedNodes.includes(node));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (this._storedNodes.length) {
|
|
89
|
+
this._storedNodes.forEach((node, index) => {
|
|
90
|
+
const idx = currentNodes.indexOf(node);
|
|
91
|
+
if (idx === -1) {
|
|
92
|
+
removedNodes.push(node);
|
|
93
|
+
} else if (idx !== index) {
|
|
94
|
+
movedNodes.push(node);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (addedNodes.length || removedNodes.length || movedNodes.length) {
|
|
100
|
+
this.callback({ addedNodes, movedNodes, removedNodes });
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
this._storedNodes = currentNodes;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2021 - 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
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Mixin to insert styles into the outer scope to handle slotted components.
|
|
10
|
+
* This is useful e.g. to hide native `<input type="number">` controls.
|
|
11
|
+
*/
|
|
12
|
+
export declare function SlotStylesMixin<T extends Constructor<HTMLElement>>(
|
|
13
|
+
base: T,
|
|
14
|
+
): Constructor<SlotStylesMixinClass> & T;
|
|
15
|
+
|
|
16
|
+
export declare class SlotStylesMixinClass {
|
|
17
|
+
/**
|
|
18
|
+
* List of styles to insert into root.
|
|
19
|
+
*/
|
|
20
|
+
protected readonly slotStyles: string[];
|
|
21
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2021 - 2023 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
|
|
7
|
+
|
|
8
|
+
const stylesMap = new WeakMap();
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Get all the styles inserted into root.
|
|
12
|
+
* @param {DocumentOrShadowRoot} root
|
|
13
|
+
* @return {Set<string>}
|
|
14
|
+
*/
|
|
15
|
+
function getRootStyles(root) {
|
|
16
|
+
if (!stylesMap.has(root)) {
|
|
17
|
+
stylesMap.set(root, new Set());
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return stylesMap.get(root);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Insert styles into the root.
|
|
25
|
+
* @param {string} styles
|
|
26
|
+
* @param {DocumentOrShadowRoot} root
|
|
27
|
+
*/
|
|
28
|
+
function insertStyles(styles, root) {
|
|
29
|
+
const style = document.createElement('style');
|
|
30
|
+
style.textContent = styles;
|
|
31
|
+
|
|
32
|
+
if (root === document) {
|
|
33
|
+
document.head.appendChild(style);
|
|
34
|
+
} else {
|
|
35
|
+
root.insertBefore(style, root.firstChild);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Mixin to insert styles into the outer scope to handle slotted components.
|
|
41
|
+
* This is useful e.g. to hide native `<input type="number">` controls.
|
|
42
|
+
*
|
|
43
|
+
* @polymerMixin
|
|
44
|
+
*/
|
|
45
|
+
export const SlotStylesMixin = dedupingMixin(
|
|
46
|
+
(superclass) =>
|
|
47
|
+
class SlotStylesMixinClass extends superclass {
|
|
48
|
+
/**
|
|
49
|
+
* List of styles to insert into root.
|
|
50
|
+
* @protected
|
|
51
|
+
*/
|
|
52
|
+
get slotStyles() {
|
|
53
|
+
return {};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** @protected */
|
|
57
|
+
connectedCallback() {
|
|
58
|
+
super.connectedCallback();
|
|
59
|
+
|
|
60
|
+
this.__applySlotStyles();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** @private */
|
|
64
|
+
__applySlotStyles() {
|
|
65
|
+
const root = this.getRootNode();
|
|
66
|
+
const rootStyles = getRootStyles(root);
|
|
67
|
+
|
|
68
|
+
this.slotStyles.forEach((styles) => {
|
|
69
|
+
if (!rootStyles.has(styles)) {
|
|
70
|
+
insertStyles(styles, root);
|
|
71
|
+
rootStyles.add(styles);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
);
|
|
@@ -23,6 +23,13 @@ type TooltipPosition =
|
|
|
23
23
|
* A controller that manages the slotted tooltip element.
|
|
24
24
|
*/
|
|
25
25
|
export class TooltipController extends SlotController {
|
|
26
|
+
/**
|
|
27
|
+
* An HTML element for linking with the tooltip overlay
|
|
28
|
+
* via `aria-describedby` attribute used by screen readers.
|
|
29
|
+
* When not set, defaults to `target`.
|
|
30
|
+
*/
|
|
31
|
+
ariaTarget: HTMLElement | HTMLElement[];
|
|
32
|
+
|
|
26
33
|
/**
|
|
27
34
|
* Object with properties passed to `generator`
|
|
28
35
|
* function to be used for generating tooltip text.
|
|
@@ -51,6 +58,12 @@ export class TooltipController extends SlotController {
|
|
|
51
58
|
*/
|
|
52
59
|
target: HTMLElement;
|
|
53
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Set an HTML element for linking with the tooltip overlay
|
|
63
|
+
* via `aria-describedby` attribute used by screen readers.
|
|
64
|
+
*/
|
|
65
|
+
setAriaTarget(ariaTarget: HTMLElement | HTMLElement[]): void;
|
|
66
|
+
|
|
54
67
|
/**
|
|
55
68
|
* Set a context object to be used by generator.
|
|
56
69
|
*/
|
|
@@ -26,6 +26,10 @@ export class TooltipController extends SlotController {
|
|
|
26
26
|
initCustomNode(tooltipNode) {
|
|
27
27
|
tooltipNode.target = this.target;
|
|
28
28
|
|
|
29
|
+
if (this.ariaTarget !== undefined) {
|
|
30
|
+
tooltipNode.ariaTarget = this.ariaTarget;
|
|
31
|
+
}
|
|
32
|
+
|
|
29
33
|
if (this.context !== undefined) {
|
|
30
34
|
tooltipNode.context = this.context;
|
|
31
35
|
}
|
|
@@ -45,6 +49,33 @@ export class TooltipController extends SlotController {
|
|
|
45
49
|
if (this.shouldShow !== undefined) {
|
|
46
50
|
tooltipNode.shouldShow = this.shouldShow;
|
|
47
51
|
}
|
|
52
|
+
|
|
53
|
+
this.__notifyChange();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Override to notify the host when the tooltip is removed.
|
|
58
|
+
*
|
|
59
|
+
* @param {Node} tooltipNode
|
|
60
|
+
* @protected
|
|
61
|
+
* @override
|
|
62
|
+
*/
|
|
63
|
+
teardownNode() {
|
|
64
|
+
this.__notifyChange();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Set an HTML element for linking with the tooltip overlay
|
|
69
|
+
* via `aria-describedby` attribute used by screen readers.
|
|
70
|
+
* @param {HTMLElement} ariaTarget
|
|
71
|
+
*/
|
|
72
|
+
setAriaTarget(ariaTarget) {
|
|
73
|
+
this.ariaTarget = ariaTarget;
|
|
74
|
+
|
|
75
|
+
const tooltipNode = this.node;
|
|
76
|
+
if (tooltipNode) {
|
|
77
|
+
tooltipNode.ariaTarget = ariaTarget;
|
|
78
|
+
}
|
|
48
79
|
}
|
|
49
80
|
|
|
50
81
|
/**
|
|
@@ -127,4 +158,9 @@ export class TooltipController extends SlotController {
|
|
|
127
158
|
tooltipNode.target = target;
|
|
128
159
|
}
|
|
129
160
|
}
|
|
161
|
+
|
|
162
|
+
/** @private */
|
|
163
|
+
__notifyChange() {
|
|
164
|
+
this.dispatchEvent(new CustomEvent('tooltip-changed', { detail: { node: this.node } }));
|
|
165
|
+
}
|
|
130
166
|
}
|
|
@@ -82,10 +82,24 @@ export class IronListAdapter {
|
|
|
82
82
|
return this.lastVisibleIndex + this._vidxOffset;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
__hasPlaceholders() {
|
|
86
|
+
return this.__getVisibleElements().some((el) => el.__virtualizerPlaceholder);
|
|
87
|
+
}
|
|
88
|
+
|
|
85
89
|
scrollToIndex(index) {
|
|
86
90
|
if (typeof index !== 'number' || isNaN(index) || this.size === 0 || !this.scrollTarget.offsetHeight) {
|
|
87
91
|
return;
|
|
88
92
|
}
|
|
93
|
+
delete this.__pendingScrollToIndex;
|
|
94
|
+
|
|
95
|
+
if (this._physicalCount <= 3 /* iron-list-core.DEFAULT_PHYSICAL_COUNT */) {
|
|
96
|
+
// The condition here is a performance improvement to avoid an unnecessary
|
|
97
|
+
// re-render when the physical item pool is already covered.
|
|
98
|
+
|
|
99
|
+
// Finish rendering at the current scroll position before scrolling
|
|
100
|
+
this.flush();
|
|
101
|
+
}
|
|
102
|
+
|
|
89
103
|
index = this._clamp(index, 0, this.size - 1);
|
|
90
104
|
|
|
91
105
|
const visibleElementCount = this.__getVisibleElements().length;
|
|
@@ -113,6 +127,12 @@ export class IronListAdapter {
|
|
|
113
127
|
this._scrollTop -= this.__getIndexScrollOffset(index) || 0;
|
|
114
128
|
}
|
|
115
129
|
this._scrollHandler();
|
|
130
|
+
|
|
131
|
+
if (this.__hasPlaceholders()) {
|
|
132
|
+
// After rendering synchronously, there are still placeholders in the DOM.
|
|
133
|
+
// Try again after the next elements update.
|
|
134
|
+
this.__pendingScrollToIndex = index;
|
|
135
|
+
}
|
|
116
136
|
}
|
|
117
137
|
|
|
118
138
|
flush() {
|
|
@@ -199,8 +219,9 @@ export class IronListAdapter {
|
|
|
199
219
|
|
|
200
220
|
__updateElement(el, index, forceSameIndexUpdates) {
|
|
201
221
|
// Clean up temporary placeholder sizing
|
|
202
|
-
if (el.
|
|
222
|
+
if (el.__virtualizerPlaceholder) {
|
|
203
223
|
el.style.paddingTop = '';
|
|
224
|
+
el.__virtualizerPlaceholder = false;
|
|
204
225
|
}
|
|
205
226
|
|
|
206
227
|
if (!this.__preventElementUpdates && (el.__lastUpdatedIndex !== index || forceSameIndexUpdates)) {
|
|
@@ -224,6 +245,7 @@ export class IronListAdapter {
|
|
|
224
245
|
// Assign a temporary placeholder sizing to elements that would otherwise end up having
|
|
225
246
|
// no height.
|
|
226
247
|
el.style.paddingTop = `${this.__placeholderHeight}px`;
|
|
248
|
+
el.__virtualizerPlaceholder = true;
|
|
227
249
|
|
|
228
250
|
// Manually schedule the resize handler to make sure the placeholder padding is
|
|
229
251
|
// cleared in case the resize observer never triggers.
|
|
@@ -241,6 +263,10 @@ export class IronListAdapter {
|
|
|
241
263
|
this.__placeholderHeight = Math.round(filteredHeights.reduce((a, b) => a + b, 0) / filteredHeights.length);
|
|
242
264
|
}
|
|
243
265
|
});
|
|
266
|
+
|
|
267
|
+
if (this.__pendingScrollToIndex !== undefined && !this.__hasPlaceholders()) {
|
|
268
|
+
this.scrollToIndex(this.__pendingScrollToIndex);
|
|
269
|
+
}
|
|
244
270
|
}
|
|
245
271
|
|
|
246
272
|
__getIndexScrollOffset(index) {
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import { Cache } from './data-provider-controller/cache.js';
|
|
2
|
-
import { getFlatIndexByPath, getFlatIndexInfo } from './data-provider-controller/helpers.js';
|
|
3
|
-
|
|
4
|
-
export class DataProviderController extends EventTarget {
|
|
5
|
-
constructor(host, { size, pageSize, isExpanded, dataProvider, dataProviderParams }) {
|
|
6
|
-
super();
|
|
7
|
-
this.host = host;
|
|
8
|
-
this.size = size;
|
|
9
|
-
this.pageSize = pageSize;
|
|
10
|
-
this.isExpanded = isExpanded;
|
|
11
|
-
this.dataProvider = dataProvider;
|
|
12
|
-
this.dataProviderParams = dataProviderParams;
|
|
13
|
-
this.rootCache = this.#createRootCache();
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
get effectiveSize() {
|
|
17
|
-
return this.rootCache.effectiveSize;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
isLoading() {
|
|
21
|
-
return this.rootCache.isLoading;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
setSize(size) {
|
|
25
|
-
const delta = size - this.rootCache.size;
|
|
26
|
-
this.size = size;
|
|
27
|
-
this.rootCache.size += delta;
|
|
28
|
-
this.rootCache.effectiveSize += delta;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
setPageSize(pageSize) {
|
|
32
|
-
this.pageSize = pageSize;
|
|
33
|
-
this.clearCache();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
setDataProvider(dataProvider) {
|
|
37
|
-
this.dataProvider = dataProvider;
|
|
38
|
-
this.clearCache();
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
recalculateEffectiveSize() {
|
|
42
|
-
this.rootCache.recalculateEffectiveSize();
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
clearCache() {
|
|
46
|
-
this.rootCache = this.#createRootCache();
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
getFlatIndexInfo(flatIndex) {
|
|
50
|
-
return getFlatIndexInfo(this.rootCache, flatIndex);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
getFlatIndexByPath(path) {
|
|
54
|
-
return getFlatIndexByPath(this.rootCache, path);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
ensureFlatIndexLoaded(flatIndex) {
|
|
58
|
-
const { cache, page, item } = this.getFlatIndexInfo(flatIndex);
|
|
59
|
-
|
|
60
|
-
if (!item) {
|
|
61
|
-
this.#loadCachePage(cache, page);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
ensureFlatIndexChildrenLoaded(flatIndex) {
|
|
66
|
-
const { cache, item, index } = this.getFlatIndexInfo(flatIndex);
|
|
67
|
-
|
|
68
|
-
if (item && this.isExpanded(item)) {
|
|
69
|
-
let subCache = cache.getSubCache(index);
|
|
70
|
-
if (!subCache) {
|
|
71
|
-
subCache = cache.createSubCache(index);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (!subCache.isPageLoaded(0)) {
|
|
75
|
-
this.#loadCachePage(subCache, 0);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
ensureFirstPageLoaded() {
|
|
81
|
-
if (!this.rootCache.isPageLoaded(0)) {
|
|
82
|
-
this.#loadCachePage(this.rootCache, 0);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
#createRootCache() {
|
|
87
|
-
return new Cache(this, this.pageSize, this.size);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
#loadCachePage(cache, page) {
|
|
91
|
-
if (!this.dataProvider || cache.pendingRequests.has(page)) {
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const params = {
|
|
96
|
-
page,
|
|
97
|
-
pageSize: this.pageSize,
|
|
98
|
-
parentItem: cache.parentItem,
|
|
99
|
-
...this.dataProviderParams(),
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
const callback = (items, size) => {
|
|
103
|
-
if (size !== undefined) {
|
|
104
|
-
cache.size = size;
|
|
105
|
-
} else if (params.parentItem) {
|
|
106
|
-
cache.size = items.length;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
cache.setPage(page, items);
|
|
110
|
-
|
|
111
|
-
this.recalculateEffectiveSize();
|
|
112
|
-
|
|
113
|
-
this.dispatchEvent(new CustomEvent('page-received'));
|
|
114
|
-
|
|
115
|
-
cache.pendingRequests.delete(page);
|
|
116
|
-
|
|
117
|
-
this.dispatchEvent(new CustomEvent('page-loaded'));
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
cache.pendingRequests.set(page, callback);
|
|
121
|
-
|
|
122
|
-
this.dispatchEvent(new CustomEvent('page-requested'));
|
|
123
|
-
|
|
124
|
-
this.dataProvider(params, callback);
|
|
125
|
-
}
|
|
126
|
-
}
|