@vaadin/component-base 23.3.3 → 24.0.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/index.d.ts +0 -1
- package/index.js +0 -1
- package/package.json +2 -2
- package/src/a11y-announcer.d.ts +1 -1
- package/src/a11y-announcer.js +1 -1
- package/src/active-mixin.d.ts +1 -1
- package/src/active-mixin.js +1 -1
- package/src/browser-utils.js +7 -7
- package/src/controller-mixin.d.ts +1 -1
- package/src/controller-mixin.js +1 -1
- package/src/delegate-focus-mixin.d.ts +48 -0
- package/src/delegate-focus-mixin.js +228 -0
- package/src/delegate-state-mixin.d.ts +20 -0
- package/src/delegate-state-mixin.js +125 -0
- package/src/dir-mixin.d.ts +2 -4
- package/src/dir-mixin.js +7 -29
- package/src/dir-utils.d.ts +19 -0
- package/src/dir-utils.js +36 -0
- package/src/disabled-mixin.d.ts +1 -1
- package/src/disabled-mixin.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 +11 -5
- package/src/focus-mixin.d.ts +1 -1
- package/src/focus-mixin.js +1 -1
- package/src/focus-trap-controller.d.ts +1 -1
- package/src/focus-trap-controller.js +22 -22
- package/src/focus-utils.d.ts +1 -1
- package/src/focus-utils.js +1 -1
- package/src/gestures.js +1 -1
- package/src/iron-list-core.js +21 -11
- package/src/keyboard-direction-mixin.d.ts +1 -1
- package/src/keyboard-direction-mixin.js +12 -12
- package/src/keyboard-mixin.d.ts +1 -1
- package/src/keyboard-mixin.js +1 -1
- package/src/list-mixin.d.ts +50 -0
- package/src/list-mixin.js +343 -0
- 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 +33 -0
- package/src/overlay-class-mixin.js +79 -0
- package/src/polylit-mixin.d.ts +1 -1
- package/src/polylit-mixin.js +9 -4
- package/src/resize-mixin.d.ts +1 -1
- package/src/resize-mixin.js +11 -21
- package/src/slot-child-observe-controller.d.ts +28 -0
- package/src/slot-child-observe-controller.js +176 -0
- package/src/slot-controller.d.ts +33 -5
- package/src/slot-controller.js +103 -40
- package/src/tabindex-mixin.d.ts +1 -1
- package/src/tabindex-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/virtualizer-iron-list-adapter.js +6 -2
- package/src/virtualizer.js +18 -18
- package/src/dir-helper.d.ts +0 -42
- package/src/dir-helper.js +0 -93
- package/src/slot-mixin.d.ts +0 -18
- package/src/slot-mixin.js +0 -60
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2022 - 2023 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { SlotController } from './slot-controller.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A controller that observes slotted element mutations, especially ID attribute
|
|
10
|
+
* and the text content, and fires an event to notify host element about those.
|
|
11
|
+
*/
|
|
12
|
+
export class SlotChildObserveController extends SlotController {
|
|
13
|
+
constructor(host, slot, tagName, config = {}) {
|
|
14
|
+
super(host, slot, tagName, { ...config, useUniqueId: true });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Override to initialize the newly added custom node.
|
|
19
|
+
*
|
|
20
|
+
* @param {Node} node
|
|
21
|
+
* @protected
|
|
22
|
+
* @override
|
|
23
|
+
*/
|
|
24
|
+
initCustomNode(node) {
|
|
25
|
+
this.__updateNodeId(node);
|
|
26
|
+
this.__notifyChange(node);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Override to notify the controller host about removal of
|
|
31
|
+
* the custom node, and to apply the default one if needed.
|
|
32
|
+
*
|
|
33
|
+
* @param {Node} _node
|
|
34
|
+
* @protected
|
|
35
|
+
* @override
|
|
36
|
+
*/
|
|
37
|
+
teardownNode(_node) {
|
|
38
|
+
const node = this.getSlotChild();
|
|
39
|
+
|
|
40
|
+
// Custom node is added to the slot
|
|
41
|
+
if (node && node !== this.defaultNode) {
|
|
42
|
+
this.__notifyChange(node);
|
|
43
|
+
} else {
|
|
44
|
+
this.restoreDefaultNode();
|
|
45
|
+
this.updateDefaultNode(this.node);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Override method inherited from `SlotMixin`
|
|
51
|
+
* to set ID attribute on the default node.
|
|
52
|
+
*
|
|
53
|
+
* @return {Node}
|
|
54
|
+
* @protected
|
|
55
|
+
* @override
|
|
56
|
+
*/
|
|
57
|
+
attachDefaultNode() {
|
|
58
|
+
const node = super.attachDefaultNode();
|
|
59
|
+
|
|
60
|
+
if (node) {
|
|
61
|
+
this.__updateNodeId(node);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return node;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Override to restore default node when a custom one is removed.
|
|
69
|
+
*
|
|
70
|
+
* @protected
|
|
71
|
+
*/
|
|
72
|
+
restoreDefaultNode() {
|
|
73
|
+
// To be implemented
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Override to update default node text on property change.
|
|
78
|
+
*
|
|
79
|
+
* @param {Node} node
|
|
80
|
+
* @protected
|
|
81
|
+
*/
|
|
82
|
+
updateDefaultNode(node) {
|
|
83
|
+
this.__notifyChange(node);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Setup the mutation observer on the node to update ID and notify host.
|
|
88
|
+
* Node doesn't get observed automatically until this method is called.
|
|
89
|
+
*
|
|
90
|
+
* @param {Node} node
|
|
91
|
+
* @protected
|
|
92
|
+
*/
|
|
93
|
+
observeNode(node) {
|
|
94
|
+
// Stop observing the previous node, if any.
|
|
95
|
+
if (this.__nodeObserver) {
|
|
96
|
+
this.__nodeObserver.disconnect();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
this.__nodeObserver = new MutationObserver((mutations) => {
|
|
100
|
+
mutations.forEach((mutation) => {
|
|
101
|
+
const target = mutation.target;
|
|
102
|
+
|
|
103
|
+
// Ensure the mutation target is the currently connected node
|
|
104
|
+
// to ignore async mutations dispatched for removed element.
|
|
105
|
+
const isCurrentNodeMutation = target === this.node;
|
|
106
|
+
|
|
107
|
+
if (mutation.type === 'attributes') {
|
|
108
|
+
// We use attributeFilter to only observe ID mutation,
|
|
109
|
+
// no need to check for attribute name separately.
|
|
110
|
+
if (isCurrentNodeMutation) {
|
|
111
|
+
this.__updateNodeId(target);
|
|
112
|
+
}
|
|
113
|
+
} else if (isCurrentNodeMutation || target.parentElement === this.node) {
|
|
114
|
+
// Node text content has changed.
|
|
115
|
+
this.__notifyChange(this.node);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// Observe changes to node ID attribute, text content and children.
|
|
121
|
+
this.__nodeObserver.observe(node, {
|
|
122
|
+
attributes: true,
|
|
123
|
+
attributeFilter: ['id'],
|
|
124
|
+
childList: true,
|
|
125
|
+
subtree: true,
|
|
126
|
+
characterData: true,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Returns true if a node is an HTML element with children,
|
|
132
|
+
* or is a defined custom element, or has non-empty text.
|
|
133
|
+
*
|
|
134
|
+
* @param {Node} node
|
|
135
|
+
* @return {boolean}
|
|
136
|
+
* @private
|
|
137
|
+
*/
|
|
138
|
+
__hasContent(node) {
|
|
139
|
+
if (!node) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return (
|
|
144
|
+
(node.nodeType === Node.ELEMENT_NODE && (customElements.get(node.localName) || node.children.length > 0)) ||
|
|
145
|
+
(node.textContent && node.textContent.trim() !== '')
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Fire an event to notify the controller host about node changes.
|
|
151
|
+
*
|
|
152
|
+
* @param {Node} node
|
|
153
|
+
* @private
|
|
154
|
+
*/
|
|
155
|
+
__notifyChange(node) {
|
|
156
|
+
this.dispatchEvent(
|
|
157
|
+
new CustomEvent('slot-content-changed', {
|
|
158
|
+
detail: { hasContent: this.__hasContent(node), node },
|
|
159
|
+
}),
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Set default ID on the node in case it is an HTML element.
|
|
165
|
+
*
|
|
166
|
+
* @param {Node} node
|
|
167
|
+
* @private
|
|
168
|
+
*/
|
|
169
|
+
__updateNodeId(node) {
|
|
170
|
+
// When in multiple mode, only set ID attribute on the element in default slot.
|
|
171
|
+
const isFirstNode = !this.nodes || node === this.nodes[0];
|
|
172
|
+
if (node.nodeType === Node.ELEMENT_NODE && isFirstNode && !node.id) {
|
|
173
|
+
node.id = this.defaultId;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
package/src/slot-controller.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2023 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 { ReactiveController } from 'lit';
|
|
@@ -16,8 +16,16 @@ export class SlotController extends EventTarget implements ReactiveController {
|
|
|
16
16
|
*/
|
|
17
17
|
node: HTMLElement;
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* The list of slotted nodes managed by the controller.
|
|
21
|
+
* Only used when `multiple` property is set to `true`.
|
|
22
|
+
*/
|
|
23
|
+
nodes: HTMLElement[];
|
|
24
|
+
|
|
19
25
|
protected initialized: boolean;
|
|
20
26
|
|
|
27
|
+
protected multiple: boolean;
|
|
28
|
+
|
|
21
29
|
protected defaultNode: Node;
|
|
22
30
|
|
|
23
31
|
protected defaultId: string;
|
|
@@ -25,20 +33,40 @@ export class SlotController extends EventTarget implements ReactiveController {
|
|
|
25
33
|
constructor(
|
|
26
34
|
host: HTMLElement,
|
|
27
35
|
slotName: string,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
36
|
+
tagName?: string,
|
|
37
|
+
config?: {
|
|
38
|
+
multiple?: boolean;
|
|
39
|
+
observe?: boolean;
|
|
40
|
+
useUniqueId?: boolean;
|
|
41
|
+
initializer?(host: HTMLElement, node: HTMLElement): void;
|
|
42
|
+
},
|
|
31
43
|
);
|
|
32
44
|
|
|
33
45
|
hostConnected(): void;
|
|
34
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Return the list of nodes matching the slot managed by the controller.
|
|
49
|
+
*/
|
|
50
|
+
getSlotChildren(): Node[];
|
|
51
|
+
|
|
35
52
|
/**
|
|
36
53
|
* Return a reference to the node managed by the controller.
|
|
37
54
|
*/
|
|
38
55
|
getSlotChild(): Node;
|
|
39
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Create and attach default node using the provided tag name, if any.
|
|
59
|
+
*/
|
|
40
60
|
protected attachDefaultNode(): Node | undefined;
|
|
41
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Run both `initCustomNode` and `initNode` for a custom slotted node.
|
|
64
|
+
*/
|
|
65
|
+
protected initAddedNode(node: Node): void;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Run `slotInitializer` for the node managed by the controller.
|
|
69
|
+
*/
|
|
42
70
|
protected initNode(node: Node): void;
|
|
43
71
|
|
|
44
72
|
/**
|
|
@@ -54,5 +82,5 @@ export class SlotController extends EventTarget implements ReactiveController {
|
|
|
54
82
|
/**
|
|
55
83
|
* Setup the observer to manage slot content changes.
|
|
56
84
|
*/
|
|
57
|
-
protected
|
|
85
|
+
protected observeSlot(): void;
|
|
58
86
|
}
|
package/src/slot-controller.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2023 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 { FlattenedNodesObserver } from '@polymer/polymer/lib/utils/flattened-nodes-observer.js';
|
|
7
|
+
import { isEmptyTextNode } from './dom-utils.js';
|
|
7
8
|
import { generateUniqueId } from './unique-id-utils.js';
|
|
8
9
|
|
|
9
10
|
/**
|
|
@@ -13,64 +14,97 @@ export class SlotController extends EventTarget {
|
|
|
13
14
|
/**
|
|
14
15
|
* Ensure that every instance has unique ID.
|
|
15
16
|
*
|
|
16
|
-
* @param {string} slotName
|
|
17
17
|
* @param {HTMLElement} host
|
|
18
|
+
* @param {string} slotName
|
|
18
19
|
* @return {string}
|
|
19
20
|
* @protected
|
|
20
21
|
*/
|
|
21
|
-
static generateId(
|
|
22
|
+
static generateId(host, slotName) {
|
|
22
23
|
const prefix = slotName || 'default';
|
|
23
24
|
return `${prefix}-${host.localName}-${generateUniqueId()}`;
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
constructor(host, slotName,
|
|
27
|
+
constructor(host, slotName, tagName, config = {}) {
|
|
27
28
|
super();
|
|
28
29
|
|
|
30
|
+
const { initializer, multiple, observe, useUniqueId } = config;
|
|
31
|
+
|
|
29
32
|
this.host = host;
|
|
30
33
|
this.slotName = slotName;
|
|
31
|
-
this.
|
|
32
|
-
this.
|
|
34
|
+
this.tagName = tagName;
|
|
35
|
+
this.observe = typeof observe === 'boolean' ? observe : true;
|
|
36
|
+
this.multiple = typeof multiple === 'boolean' ? multiple : false;
|
|
37
|
+
this.slotInitializer = initializer;
|
|
38
|
+
|
|
39
|
+
if (multiple) {
|
|
40
|
+
this.nodes = [];
|
|
41
|
+
}
|
|
33
42
|
|
|
34
43
|
// Only generate the default ID if requested by the controller.
|
|
35
44
|
if (useUniqueId) {
|
|
36
|
-
this.defaultId =
|
|
45
|
+
this.defaultId = this.constructor.generateId(host, slotName);
|
|
37
46
|
}
|
|
38
47
|
}
|
|
39
48
|
|
|
40
49
|
hostConnected() {
|
|
41
50
|
if (!this.initialized) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (!node) {
|
|
45
|
-
node = this.attachDefaultNode();
|
|
51
|
+
if (this.multiple) {
|
|
52
|
+
this.initMultiple();
|
|
46
53
|
} else {
|
|
47
|
-
this.
|
|
48
|
-
this.initCustomNode(node);
|
|
54
|
+
this.initSingle();
|
|
49
55
|
}
|
|
50
56
|
|
|
51
|
-
this.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
this.observe();
|
|
57
|
+
if (this.observe) {
|
|
58
|
+
this.observeSlot();
|
|
59
|
+
}
|
|
55
60
|
|
|
56
61
|
this.initialized = true;
|
|
57
62
|
}
|
|
58
63
|
}
|
|
59
64
|
|
|
65
|
+
/** @protected */
|
|
66
|
+
initSingle() {
|
|
67
|
+
let node = this.getSlotChild();
|
|
68
|
+
|
|
69
|
+
if (!node) {
|
|
70
|
+
node = this.attachDefaultNode();
|
|
71
|
+
this.initNode(node);
|
|
72
|
+
} else {
|
|
73
|
+
this.node = node;
|
|
74
|
+
this.initAddedNode(node);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** @protected */
|
|
79
|
+
initMultiple() {
|
|
80
|
+
const children = this.getSlotChildren();
|
|
81
|
+
|
|
82
|
+
if (children.length === 0) {
|
|
83
|
+
const defaultNode = this.attachDefaultNode();
|
|
84
|
+
this.nodes = [defaultNode];
|
|
85
|
+
this.initNode(defaultNode);
|
|
86
|
+
} else {
|
|
87
|
+
this.nodes = children;
|
|
88
|
+
children.forEach((node) => {
|
|
89
|
+
this.initAddedNode(node);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
60
94
|
/**
|
|
61
|
-
* Create and attach default node using the
|
|
95
|
+
* Create and attach default node using the provided tag name, if any.
|
|
62
96
|
* @return {Node | undefined}
|
|
63
97
|
* @protected
|
|
64
98
|
*/
|
|
65
99
|
attachDefaultNode() {
|
|
66
|
-
const { host, slotName,
|
|
100
|
+
const { host, slotName, tagName } = this;
|
|
67
101
|
|
|
68
102
|
// Check if the node was created previously and if so, reuse it.
|
|
69
103
|
let node = this.defaultNode;
|
|
70
104
|
|
|
71
|
-
//
|
|
72
|
-
if (!node &&
|
|
73
|
-
node =
|
|
105
|
+
// Tag name is optional, sometimes we don't init default content.
|
|
106
|
+
if (!node && tagName) {
|
|
107
|
+
node = document.createElement(tagName);
|
|
74
108
|
if (node instanceof Element) {
|
|
75
109
|
if (slotName !== '') {
|
|
76
110
|
node.setAttribute('slot', slotName);
|
|
@@ -88,12 +122,12 @@ export class SlotController extends EventTarget {
|
|
|
88
122
|
}
|
|
89
123
|
|
|
90
124
|
/**
|
|
91
|
-
* Return
|
|
125
|
+
* Return the list of nodes matching the slot managed by the controller.
|
|
92
126
|
* @return {Node}
|
|
93
127
|
*/
|
|
94
|
-
|
|
128
|
+
getSlotChildren() {
|
|
95
129
|
const { slotName } = this;
|
|
96
|
-
return Array.from(this.host.childNodes).
|
|
130
|
+
return Array.from(this.host.childNodes).filter((node) => {
|
|
97
131
|
// Either an element (any slot) or a text node (only un-named slot).
|
|
98
132
|
return (
|
|
99
133
|
(node.nodeType === Node.ELEMENT_NODE && node.slot === slotName) ||
|
|
@@ -103,6 +137,16 @@ export class SlotController extends EventTarget {
|
|
|
103
137
|
}
|
|
104
138
|
|
|
105
139
|
/**
|
|
140
|
+
* Return a reference to the node managed by the controller.
|
|
141
|
+
* @return {Node}
|
|
142
|
+
*/
|
|
143
|
+
getSlotChild() {
|
|
144
|
+
return this.getSlotChildren()[0];
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Run `slotInitializer` for the node managed by the controller.
|
|
149
|
+
*
|
|
106
150
|
* @param {Node} node
|
|
107
151
|
* @protected
|
|
108
152
|
*/
|
|
@@ -111,7 +155,7 @@ export class SlotController extends EventTarget {
|
|
|
111
155
|
// Don't try to bind `this` to initializer (normally it's arrow function).
|
|
112
156
|
// Instead, pass the host as a first argument to access component's state.
|
|
113
157
|
if (slotInitializer) {
|
|
114
|
-
slotInitializer(this.host
|
|
158
|
+
slotInitializer(node, this.host);
|
|
115
159
|
}
|
|
116
160
|
}
|
|
117
161
|
|
|
@@ -131,19 +175,34 @@ export class SlotController extends EventTarget {
|
|
|
131
175
|
*/
|
|
132
176
|
teardownNode(_node) {}
|
|
133
177
|
|
|
178
|
+
/**
|
|
179
|
+
* Run both `initCustomNode` and `initNode` for a custom slotted node.
|
|
180
|
+
*
|
|
181
|
+
* @param {Node} node
|
|
182
|
+
* @protected
|
|
183
|
+
*/
|
|
184
|
+
initAddedNode(node) {
|
|
185
|
+
if (node !== this.defaultNode) {
|
|
186
|
+
this.initCustomNode(node);
|
|
187
|
+
this.initNode(node);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
134
191
|
/**
|
|
135
192
|
* Setup the observer to manage slot content changes.
|
|
136
193
|
* @protected
|
|
137
194
|
*/
|
|
138
|
-
|
|
195
|
+
observeSlot() {
|
|
139
196
|
const { slotName } = this;
|
|
140
197
|
const selector = slotName === '' ? 'slot:not([name])' : `slot[name=${slotName}]`;
|
|
141
198
|
const slot = this.host.shadowRoot.querySelector(selector);
|
|
142
199
|
|
|
143
200
|
this.__slotObserver = new FlattenedNodesObserver(slot, (info) => {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
201
|
+
const current = this.multiple ? this.nodes : [this.node];
|
|
202
|
+
|
|
203
|
+
// Calling `slot.assignedNodes()` includes whitespace text nodes in case of default slot:
|
|
204
|
+
// unlike comment nodes, they are not filtered out. So we need to manually ignore them.
|
|
205
|
+
const newNodes = info.addedNodes.filter((node) => !isEmptyTextNode(node) && !current.includes(node));
|
|
147
206
|
|
|
148
207
|
if (info.removedNodes.length) {
|
|
149
208
|
info.removedNodes.forEach((node) => {
|
|
@@ -151,18 +210,22 @@ export class SlotController extends EventTarget {
|
|
|
151
210
|
});
|
|
152
211
|
}
|
|
153
212
|
|
|
154
|
-
if (
|
|
213
|
+
if (newNodes && newNodes.length > 0) {
|
|
155
214
|
// Custom node is added, remove the current one.
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
if (newNode !== this.defaultNode) {
|
|
163
|
-
this.initCustomNode(newNode);
|
|
215
|
+
current.forEach((node) => {
|
|
216
|
+
if (node && node.isConnected) {
|
|
217
|
+
node.parentNode.removeChild(node);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
164
220
|
|
|
165
|
-
|
|
221
|
+
if (this.multiple) {
|
|
222
|
+
this.nodes = newNodes;
|
|
223
|
+
newNodes.forEach((node) => {
|
|
224
|
+
this.initAddedNode(node);
|
|
225
|
+
});
|
|
226
|
+
} else {
|
|
227
|
+
this.node = newNodes[0];
|
|
228
|
+
this.initAddedNode(this.node);
|
|
166
229
|
}
|
|
167
230
|
}
|
|
168
231
|
});
|
package/src/tabindex-mixin.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2023 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/tabindex-mixin.js
CHANGED
package/src/templates.js
CHANGED
package/src/unique-id-utils.d.ts
CHANGED
package/src/unique-id-utils.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
3
|
+
* Copyright (c) 2021 - 2023 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
|
+
/* eslint-disable @typescript-eslint/member-ordering */
|
|
7
|
+
// https://github.com/vaadin/eslint-config-vaadin/issues/33
|
|
6
8
|
import { animationFrame, timeOut } from './async.js';
|
|
7
9
|
import { isSafari } from './browser-utils.js';
|
|
8
10
|
import { Debouncer, flush } from './debounce.js';
|
|
@@ -430,7 +432,9 @@ export class IronListAdapter {
|
|
|
430
432
|
deltaY *= this._scrollPageHeight;
|
|
431
433
|
}
|
|
432
434
|
|
|
433
|
-
|
|
435
|
+
if (!this._deltaYAcc) {
|
|
436
|
+
this._deltaYAcc = 0;
|
|
437
|
+
}
|
|
434
438
|
|
|
435
439
|
if (this._wheelAnimationFrame) {
|
|
436
440
|
// Accumulate wheel delta while a frame is being processed
|
package/src/virtualizer.js
CHANGED
|
@@ -15,6 +15,24 @@ export class Virtualizer {
|
|
|
15
15
|
this.__adapter = new IronListAdapter(config);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Gets the index of the first visible item in the viewport.
|
|
20
|
+
*
|
|
21
|
+
* @return {number}
|
|
22
|
+
*/
|
|
23
|
+
get firstVisibleIndex() {
|
|
24
|
+
return this.__adapter.adjustedFirstVisibleIndex;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Gets the index of the last visible item in the viewport.
|
|
29
|
+
*
|
|
30
|
+
* @return {number}
|
|
31
|
+
*/
|
|
32
|
+
get lastVisibleIndex() {
|
|
33
|
+
return this.__adapter.adjustedLastVisibleIndex;
|
|
34
|
+
}
|
|
35
|
+
|
|
18
36
|
/**
|
|
19
37
|
* The size of the virtualizer
|
|
20
38
|
* @return {number | undefined} The size of the virtualizer
|
|
@@ -62,22 +80,4 @@ export class Virtualizer {
|
|
|
62
80
|
flush() {
|
|
63
81
|
this.__adapter.flush();
|
|
64
82
|
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Gets the index of the first visible item in the viewport.
|
|
68
|
-
*
|
|
69
|
-
* @return {number}
|
|
70
|
-
*/
|
|
71
|
-
get firstVisibleIndex() {
|
|
72
|
-
return this.__adapter.adjustedFirstVisibleIndex;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Gets the index of the last visible item in the viewport.
|
|
77
|
-
*
|
|
78
|
-
* @return {number}
|
|
79
|
-
*/
|
|
80
|
-
get lastVisibleIndex() {
|
|
81
|
-
return this.__adapter.adjustedLastVisibleIndex;
|
|
82
|
-
}
|
|
83
83
|
}
|
package/src/dir-helper.d.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2021 - 2022 Vaadin Ltd.
|
|
4
|
-
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Helper that provides a set of functions for RTL.
|
|
9
|
-
*/
|
|
10
|
-
declare class DirHelper {
|
|
11
|
-
/**
|
|
12
|
-
* Get the scroll type in the current browser view.
|
|
13
|
-
*
|
|
14
|
-
* @returns the scroll type. Possible values are `default|reverse|negative`
|
|
15
|
-
*/
|
|
16
|
-
static detectScrollType(): string;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Get the scrollLeft value of the element relative to the direction
|
|
20
|
-
*
|
|
21
|
-
* @param scrollType type of the scroll detected with `detectScrollType`
|
|
22
|
-
* @param direction current direction of the element
|
|
23
|
-
* @returns the scrollLeft value.
|
|
24
|
-
*/
|
|
25
|
-
static getNormalizedScrollLeft(scrollType: string, direction: string, element: Element | null): number;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Set the scrollLeft value of the element relative to the direction
|
|
29
|
-
*
|
|
30
|
-
* @param scrollType type of the scroll detected with `detectScrollType`
|
|
31
|
-
* @param direction current direction of the element
|
|
32
|
-
* @param scrollLeft the scrollLeft value to be set
|
|
33
|
-
*/
|
|
34
|
-
static setNormalizedScrollLeft(
|
|
35
|
-
scrollType: string,
|
|
36
|
-
direction: string,
|
|
37
|
-
element: Element | null,
|
|
38
|
-
scrollLeft: number,
|
|
39
|
-
): void;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export { DirHelper };
|