@vaadin/component-base 22.0.0-rc1 → 23.0.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 +2 -0
- package/index.js +2 -0
- package/package.json +2 -2
- package/src/active-mixin.js +4 -4
- package/src/async.js +3 -3
- package/src/debounce.js +10 -4
- package/src/dir-helper.js +2 -1
- package/src/dir-mixin.js +6 -6
- package/src/element-mixin.js +1 -1
- package/src/focus-trap-controller.d.ts +39 -0
- package/src/focus-trap-controller.js +139 -0
- package/src/focus-utils.d.ts +45 -0
- package/src/focus-utils.js +228 -0
- package/src/gestures.d.ts +76 -0
- package/src/gestures.js +932 -0
- package/src/iron-list-core.js +13 -11
- package/src/slot-controller.d.ts +51 -0
- package/src/slot-controller.js +122 -0
- package/src/slot-mixin.js +10 -2
- package/src/virtualizer-iron-list-adapter.js +4 -5
- package/src/virtualizer.js +6 -6
package/src/iron-list-core.js
CHANGED
|
@@ -186,6 +186,10 @@ export const ironList = {
|
|
|
186
186
|
return Math.max(0, virtualCount - this._physicalCount);
|
|
187
187
|
},
|
|
188
188
|
|
|
189
|
+
get _virtualStart() {
|
|
190
|
+
return this._virtualStartVal || 0;
|
|
191
|
+
},
|
|
192
|
+
|
|
189
193
|
set _virtualStart(val) {
|
|
190
194
|
val = this._clamp(val, 0, this._maxVirtualStart);
|
|
191
195
|
if (this.grid) {
|
|
@@ -194,8 +198,8 @@ export const ironList = {
|
|
|
194
198
|
this._virtualStartVal = val;
|
|
195
199
|
},
|
|
196
200
|
|
|
197
|
-
get
|
|
198
|
-
return this.
|
|
201
|
+
get _physicalStart() {
|
|
202
|
+
return this._physicalStartVal || 0;
|
|
199
203
|
},
|
|
200
204
|
|
|
201
205
|
/**
|
|
@@ -212,10 +216,6 @@ export const ironList = {
|
|
|
212
216
|
this._physicalStartVal = val;
|
|
213
217
|
},
|
|
214
218
|
|
|
215
|
-
get _physicalStart() {
|
|
216
|
-
return this._physicalStartVal || 0;
|
|
217
|
-
},
|
|
218
|
-
|
|
219
219
|
/**
|
|
220
220
|
* The k-th tile that is at the bottom of the scrolling list.
|
|
221
221
|
*/
|
|
@@ -223,14 +223,14 @@ export const ironList = {
|
|
|
223
223
|
return (this._physicalStart + this._physicalCount - 1) % this._physicalCount;
|
|
224
224
|
},
|
|
225
225
|
|
|
226
|
-
set _physicalCount(val) {
|
|
227
|
-
this._physicalCountVal = val;
|
|
228
|
-
},
|
|
229
|
-
|
|
230
226
|
get _physicalCount() {
|
|
231
227
|
return this._physicalCountVal || 0;
|
|
232
228
|
},
|
|
233
229
|
|
|
230
|
+
set _physicalCount(val) {
|
|
231
|
+
this._physicalCountVal = val;
|
|
232
|
+
},
|
|
233
|
+
|
|
234
234
|
/**
|
|
235
235
|
* An optimal physical size such that we will have enough physical items
|
|
236
236
|
* to fill up the viewport and recycle when the user scrolls.
|
|
@@ -548,7 +548,9 @@ export const ironList = {
|
|
|
548
548
|
},
|
|
549
549
|
|
|
550
550
|
_gridChanged: function (newGrid, oldGrid) {
|
|
551
|
-
if (typeof oldGrid === 'undefined')
|
|
551
|
+
if (typeof oldGrid === 'undefined') {
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
552
554
|
this.notifyResize();
|
|
553
555
|
flush();
|
|
554
556
|
newGrid && this._updateGridMetrics();
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2021 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { ReactiveController } from 'lit';
|
|
7
|
+
|
|
8
|
+
export class SlotController implements ReactiveController {
|
|
9
|
+
constructor(
|
|
10
|
+
host: HTMLElement,
|
|
11
|
+
slotName: string,
|
|
12
|
+
slotFactory?: () => HTMLElement,
|
|
13
|
+
slotInitializer?: (host: HTMLElement, node: HTMLElement) => void
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
hostConnected(): void;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The controller host element.
|
|
20
|
+
*/
|
|
21
|
+
host: HTMLElement;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The slotted node managed by the controller.
|
|
25
|
+
*/
|
|
26
|
+
node: HTMLElement;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Return a reference to the node managed by the controller.
|
|
30
|
+
*/
|
|
31
|
+
getSlotChild(): Node;
|
|
32
|
+
|
|
33
|
+
protected initialized: boolean;
|
|
34
|
+
|
|
35
|
+
protected defaultNode: Node;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Override to initialize the newly added custom node.
|
|
39
|
+
*/
|
|
40
|
+
protected initCustomNode(node: Node): void;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Override to cleanup slotted node when it's removed.
|
|
44
|
+
*/
|
|
45
|
+
protected teardownNode(node: Node): void;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Setup the observer to manage slot content changes.
|
|
49
|
+
*/
|
|
50
|
+
protected observe(): void;
|
|
51
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2021 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { FlattenedNodesObserver } from '@polymer/polymer/lib/utils/flattened-nodes-observer.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A controller for providing content to slot element and observing changes.
|
|
10
|
+
*/
|
|
11
|
+
export class SlotController {
|
|
12
|
+
constructor(host, slotName, slotFactory, slotInitializer) {
|
|
13
|
+
this.host = host;
|
|
14
|
+
this.slotName = slotName;
|
|
15
|
+
this.slotFactory = slotFactory;
|
|
16
|
+
this.slotInitializer = slotInitializer;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
hostConnected() {
|
|
20
|
+
if (!this.initialized) {
|
|
21
|
+
const { host, slotName, slotFactory, slotInitializer } = this;
|
|
22
|
+
|
|
23
|
+
const slotted = this.getSlotChild();
|
|
24
|
+
|
|
25
|
+
if (!slotted) {
|
|
26
|
+
// Slot factory is optional, some slots don't have default content.
|
|
27
|
+
if (slotFactory) {
|
|
28
|
+
const slotContent = slotFactory(host);
|
|
29
|
+
if (slotContent instanceof Element) {
|
|
30
|
+
if (slotName !== '') {
|
|
31
|
+
slotContent.setAttribute('slot', slotName);
|
|
32
|
+
}
|
|
33
|
+
host.appendChild(slotContent);
|
|
34
|
+
this.node = slotContent;
|
|
35
|
+
|
|
36
|
+
// Store reference to not pass default node to `initCustomNode`.
|
|
37
|
+
this.defaultNode = slotContent;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
this.node = slotted;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Don't try to bind `this` to initializer (normally it's arrow function).
|
|
45
|
+
// Instead, pass the host as a first argument to access component's state.
|
|
46
|
+
if (slotInitializer) {
|
|
47
|
+
slotInitializer(host, this.node);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// TODO: Consider making this behavior opt-in to improve performance.
|
|
51
|
+
this.observe();
|
|
52
|
+
|
|
53
|
+
this.initialized = true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Return a reference to the node managed by the controller.
|
|
59
|
+
* @return {Node}
|
|
60
|
+
*/
|
|
61
|
+
getSlotChild() {
|
|
62
|
+
const { slotName } = this;
|
|
63
|
+
return Array.from(this.host.childNodes).find((node) => {
|
|
64
|
+
// Either an element (any slot) or a text node (only un-named slot).
|
|
65
|
+
return (
|
|
66
|
+
(node.nodeType === Node.ELEMENT_NODE && node.slot === slotName) ||
|
|
67
|
+
(node.nodeType === Node.TEXT_NODE && node.textContent.trim() && slotName === '')
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Override to initialize the newly added custom node.
|
|
74
|
+
*
|
|
75
|
+
* @param {Node} _node
|
|
76
|
+
* @protected
|
|
77
|
+
*/
|
|
78
|
+
initCustomNode(_node) {}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Override to teardown slotted node when it's removed.
|
|
82
|
+
*
|
|
83
|
+
* @param {Node} _node
|
|
84
|
+
* @protected
|
|
85
|
+
*/
|
|
86
|
+
teardownNode(_node) {}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Setup the observer to manage slot content changes.
|
|
90
|
+
* @protected
|
|
91
|
+
*/
|
|
92
|
+
observe() {
|
|
93
|
+
const { slotName } = this;
|
|
94
|
+
const selector = slotName === '' ? 'slot:not([name])' : `slot[name=${slotName}]`;
|
|
95
|
+
const slot = this.host.shadowRoot.querySelector(selector);
|
|
96
|
+
|
|
97
|
+
this.__slotObserver = new FlattenedNodesObserver(slot, (info) => {
|
|
98
|
+
// TODO: support default slot with multiple nodes (e.g. confirm-dialog)
|
|
99
|
+
const current = this.node;
|
|
100
|
+
const newNode = info.addedNodes.find((node) => node !== current);
|
|
101
|
+
|
|
102
|
+
if (info.removedNodes.length) {
|
|
103
|
+
info.removedNodes.forEach((node) => {
|
|
104
|
+
this.teardownNode(node);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (newNode) {
|
|
109
|
+
// Custom node is added, remove the current one.
|
|
110
|
+
if (current && current.isConnected) {
|
|
111
|
+
this.host.removeChild(current);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
this.node = newNode;
|
|
115
|
+
|
|
116
|
+
if (newNode !== this.defaultNode) {
|
|
117
|
+
this.initCustomNode(newNode);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
package/src/slot-mixin.js
CHANGED
|
@@ -37,7 +37,9 @@ export const SlotMixin = dedupingMixin(
|
|
|
37
37
|
const slotFactory = this.slots[slotName];
|
|
38
38
|
const slotContent = slotFactory();
|
|
39
39
|
if (slotContent instanceof Element) {
|
|
40
|
-
|
|
40
|
+
if (slotName !== '') {
|
|
41
|
+
slotContent.setAttribute('slot', slotName);
|
|
42
|
+
}
|
|
41
43
|
this.appendChild(slotContent);
|
|
42
44
|
}
|
|
43
45
|
}
|
|
@@ -46,7 +48,13 @@ export const SlotMixin = dedupingMixin(
|
|
|
46
48
|
|
|
47
49
|
/** @protected */
|
|
48
50
|
_getDirectSlotChild(slotName) {
|
|
49
|
-
return Array.from(this.
|
|
51
|
+
return Array.from(this.childNodes).find((node) => {
|
|
52
|
+
// Either an element (any slot) or a text node (only un-named slot).
|
|
53
|
+
return (
|
|
54
|
+
(node.nodeType === Node.ELEMENT_NODE && node.slot === slotName) ||
|
|
55
|
+
(node.nodeType === Node.TEXT_NODE && node.textContent.trim() && slotName === '')
|
|
56
|
+
);
|
|
57
|
+
});
|
|
50
58
|
}
|
|
51
59
|
}
|
|
52
60
|
);
|
|
@@ -155,6 +155,10 @@ export class IronListAdapter {
|
|
|
155
155
|
return element ? this.scrollTarget.getBoundingClientRect().top - element.getBoundingClientRect().top : undefined;
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
get size() {
|
|
159
|
+
return this.__size;
|
|
160
|
+
}
|
|
161
|
+
|
|
158
162
|
set size(size) {
|
|
159
163
|
if (size === this.size) {
|
|
160
164
|
return;
|
|
@@ -204,10 +208,6 @@ export class IronListAdapter {
|
|
|
204
208
|
flush();
|
|
205
209
|
}
|
|
206
210
|
|
|
207
|
-
get size() {
|
|
208
|
-
return this.__size;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
211
|
/** @private */
|
|
212
212
|
get _scrollTop() {
|
|
213
213
|
return this.scrollTarget.scrollTop;
|
|
@@ -466,7 +466,6 @@ export class IronListAdapter {
|
|
|
466
466
|
this._vidxOffset = 0;
|
|
467
467
|
} else if (this.__skipNextVirtualIndexAdjust) {
|
|
468
468
|
this.__skipNextVirtualIndexAdjust = false;
|
|
469
|
-
return;
|
|
470
469
|
} else if (Math.abs(delta) > 10000) {
|
|
471
470
|
// Process a large scroll position change
|
|
472
471
|
const scale = this._scrollTop / (this.scrollTarget.scrollHeight - this.scrollTarget.offsetHeight);
|
package/src/virtualizer.js
CHANGED
|
@@ -17,18 +17,18 @@ export class Virtualizer {
|
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* The size of the virtualizer
|
|
20
|
-
* @
|
|
20
|
+
* @return {number | undefined} The size of the virtualizer
|
|
21
21
|
*/
|
|
22
|
-
|
|
23
|
-
this.__adapter.size
|
|
22
|
+
get size() {
|
|
23
|
+
return this.__adapter.size;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* The size of the virtualizer
|
|
28
|
-
* @
|
|
28
|
+
* @param {number} size The size of the virtualizer
|
|
29
29
|
*/
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
set size(size) {
|
|
31
|
+
this.__adapter.size = size;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
/**
|