@vaadin/component-base 25.2.0-alpha9 → 25.2.0-beta1
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/custom-elements.json +44 -10
- package/package.json +4 -4
- package/src/data-provider-controller/data-provider-controller.d.ts +1 -9
- package/src/data-provider-controller/helpers.js +1 -1
- package/src/define.js +1 -1
- package/src/delegate-state-mixin.js +104 -105
- package/src/dir-mixin.js +0 -2
- package/src/element-mixin.js +0 -4
- package/src/gestures.js +5 -5
- package/src/i18n-mixin.d.ts +1 -2
- package/src/i18n-mixin.js +21 -4
- package/src/overlay-class-mixin.js +0 -2
- package/src/polylit-mixin.js +1 -1
- package/src/resize-mixin.js +50 -52
- package/src/slot-controller.js +1 -1
- package/src/slot-observer.d.ts +12 -2
- package/src/slot-observer.js +63 -23
- package/src/slot-styles-mixin.js +28 -30
- package/src/styles/style-props.js +2 -3
- package/src/tooltip-controller.d.ts +16 -11
- package/src/tooltip-controller.js +28 -17
- package/src/virtualizer-iron-list-adapter.js +13 -5
package/custom-elements.json
CHANGED
|
@@ -7,9 +7,22 @@
|
|
|
7
7
|
"path": "src/delegate-state-mixin.js",
|
|
8
8
|
"declarations": [
|
|
9
9
|
{
|
|
10
|
-
"kind": "
|
|
10
|
+
"kind": "mixin",
|
|
11
|
+
"description": "",
|
|
11
12
|
"name": "DelegateStateMixin",
|
|
12
|
-
"
|
|
13
|
+
"members": [],
|
|
14
|
+
"attributes": [],
|
|
15
|
+
"parameters": [
|
|
16
|
+
{
|
|
17
|
+
"name": "superclass"
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"mixins": [
|
|
21
|
+
{
|
|
22
|
+
"name": "dedupeMixin",
|
|
23
|
+
"package": "@open-wc/dedupe-mixin"
|
|
24
|
+
}
|
|
25
|
+
]
|
|
13
26
|
}
|
|
14
27
|
],
|
|
15
28
|
"exports": [
|
|
@@ -91,7 +104,7 @@
|
|
|
91
104
|
"declarations": [
|
|
92
105
|
{
|
|
93
106
|
"kind": "mixin",
|
|
94
|
-
"description": "A mixin that allows to set partial I18N properties
|
|
107
|
+
"description": "A mixin that allows to set partial I18N properties.\n\nSubclasses provide their default values by overriding the\n`defaultI18n` static getter:\n\n```js\nstatic get defaultI18n() {\n return { foo: 'Foo', bar: 'Bar' };\n}\n```",
|
|
95
108
|
"name": "I18nMixin",
|
|
96
109
|
"members": [
|
|
97
110
|
{
|
|
@@ -116,9 +129,6 @@
|
|
|
116
129
|
}
|
|
117
130
|
],
|
|
118
131
|
"parameters": [
|
|
119
|
-
{
|
|
120
|
-
"name": "defaultI18n"
|
|
121
|
-
},
|
|
122
132
|
{
|
|
123
133
|
"name": "superClass"
|
|
124
134
|
}
|
|
@@ -223,9 +233,21 @@
|
|
|
223
233
|
"path": "src/resize-mixin.js",
|
|
224
234
|
"declarations": [
|
|
225
235
|
{
|
|
226
|
-
"kind": "
|
|
236
|
+
"kind": "mixin",
|
|
237
|
+
"description": "A mixin that uses a ResizeObserver to listen to host size changes.",
|
|
227
238
|
"name": "ResizeMixin",
|
|
228
|
-
"
|
|
239
|
+
"members": [],
|
|
240
|
+
"parameters": [
|
|
241
|
+
{
|
|
242
|
+
"name": "superclass"
|
|
243
|
+
}
|
|
244
|
+
],
|
|
245
|
+
"mixins": [
|
|
246
|
+
{
|
|
247
|
+
"name": "dedupeMixin",
|
|
248
|
+
"package": "@open-wc/dedupe-mixin"
|
|
249
|
+
}
|
|
250
|
+
]
|
|
229
251
|
}
|
|
230
252
|
],
|
|
231
253
|
"exports": [
|
|
@@ -244,9 +266,21 @@
|
|
|
244
266
|
"path": "src/slot-styles-mixin.js",
|
|
245
267
|
"declarations": [
|
|
246
268
|
{
|
|
247
|
-
"kind": "
|
|
269
|
+
"kind": "mixin",
|
|
270
|
+
"description": "Mixin to insert styles into the outer scope to handle slotted components.\nThis is useful e.g. to hide native `<input type=\"number\">` controls.",
|
|
248
271
|
"name": "SlotStylesMixin",
|
|
249
|
-
"
|
|
272
|
+
"members": [],
|
|
273
|
+
"parameters": [
|
|
274
|
+
{
|
|
275
|
+
"name": "superclass"
|
|
276
|
+
}
|
|
277
|
+
],
|
|
278
|
+
"mixins": [
|
|
279
|
+
{
|
|
280
|
+
"name": "dedupeMixin",
|
|
281
|
+
"package": "@open-wc/dedupe-mixin"
|
|
282
|
+
}
|
|
283
|
+
]
|
|
250
284
|
}
|
|
251
285
|
],
|
|
252
286
|
"exports": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/component-base",
|
|
3
|
-
"version": "25.2.0-
|
|
3
|
+
"version": "25.2.0-beta1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -38,11 +38,11 @@
|
|
|
38
38
|
"lit": "^3.0.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@vaadin/chai-plugins": "25.2.0-
|
|
42
|
-
"@vaadin/test-runner-commands": "25.2.0-
|
|
41
|
+
"@vaadin/chai-plugins": "25.2.0-beta1",
|
|
42
|
+
"@vaadin/test-runner-commands": "25.2.0-beta1",
|
|
43
43
|
"@vaadin/testing-helpers": "^2.0.0",
|
|
44
44
|
"sinon": "^21.0.2"
|
|
45
45
|
},
|
|
46
46
|
"customElements": "custom-elements.json",
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "471a23f60d1eb725f98a33f62cb9664d9c0a4163"
|
|
48
48
|
}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* Copyright (c) 2021 - 2026 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
|
-
import type { ReactiveController } from 'lit';
|
|
7
6
|
import type { Cache } from './cache.js';
|
|
8
7
|
import type { getFlatIndexByPath, getFlatIndexContext, getItemContext } from './helpers.js';
|
|
9
8
|
|
|
@@ -23,10 +22,7 @@ export type DataProvider<TItem, TDataProviderParams extends Record<string, unkno
|
|
|
23
22
|
/**
|
|
24
23
|
* A controller that stores and manages items loaded with a data provider.
|
|
25
24
|
*/
|
|
26
|
-
export class DataProviderController<
|
|
27
|
-
TItem,
|
|
28
|
-
TDataProviderParams extends Record<string, unknown>,
|
|
29
|
-
> implements ReactiveController {
|
|
25
|
+
export class DataProviderController<TItem, TDataProviderParams extends Record<string, unknown>> extends EventTarget {
|
|
30
26
|
/**
|
|
31
27
|
* The controller host element.
|
|
32
28
|
*/
|
|
@@ -94,10 +90,6 @@ export class DataProviderController<
|
|
|
94
90
|
*/
|
|
95
91
|
get flatSize(): number;
|
|
96
92
|
|
|
97
|
-
hostConnected(): void;
|
|
98
|
-
|
|
99
|
-
hostDisconnected(): void;
|
|
100
|
-
|
|
101
93
|
/**
|
|
102
94
|
* Whether the root cache or any of its decendant caches have pending requests.
|
|
103
95
|
*/
|
|
@@ -105,7 +105,7 @@ export function getFlatIndexByPath(cache, [levelIndex, ...subIndexes], flatIndex
|
|
|
105
105
|
|
|
106
106
|
const flatIndexOnLevel = cache.getFlatIndex(levelIndex);
|
|
107
107
|
const subCache = cache.getSubCache(levelIndex);
|
|
108
|
-
if (subCache
|
|
108
|
+
if (subCache?.flatSize > 0 && subIndexes.length) {
|
|
109
109
|
return getFlatIndexByPath(subCache, subIndexes, flatIndex + flatIndexOnLevel + 1);
|
|
110
110
|
}
|
|
111
111
|
return flatIndex + flatIndexOnLevel;
|
package/src/define.js
CHANGED
|
@@ -13,7 +13,7 @@ function dashToCamelCase(dash) {
|
|
|
13
13
|
|
|
14
14
|
const experimentalMap = {};
|
|
15
15
|
|
|
16
|
-
export function defineCustomElement(CustomElement, version = '25.2.0-
|
|
16
|
+
export function defineCustomElement(CustomElement, version = '25.2.0-beta1') {
|
|
17
17
|
Object.defineProperty(CustomElement, 'version', {
|
|
18
18
|
get() {
|
|
19
19
|
return version;
|
|
@@ -7,119 +7,118 @@ import { dedupeMixin } from '@open-wc/dedupe-mixin';
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* A mixin to delegate properties and attributes to a target element.
|
|
10
|
-
*
|
|
11
|
-
* @polymerMixin
|
|
12
10
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
11
|
+
const DelegateStateMixinImplementation = (superclass) => {
|
|
12
|
+
return class DelegateStateMixinClass extends superclass {
|
|
13
|
+
static get properties() {
|
|
14
|
+
return {
|
|
15
|
+
/**
|
|
16
|
+
* A target element to which attributes and properties are delegated.
|
|
17
|
+
* @protected
|
|
18
|
+
*/
|
|
19
|
+
stateTarget: {
|
|
20
|
+
type: Object,
|
|
21
|
+
observer: '_stateTargetChanged',
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* An array of the host attributes to delegate to the target element.
|
|
28
|
+
*/
|
|
29
|
+
static get delegateAttrs() {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* An array of the host properties to delegate to the target element.
|
|
35
|
+
*/
|
|
36
|
+
static get delegateProps() {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** @protected */
|
|
41
|
+
ready() {
|
|
42
|
+
super.ready();
|
|
43
|
+
|
|
44
|
+
this._createDelegateAttrsObserver();
|
|
45
|
+
this._createDelegatePropsObserver();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** @protected */
|
|
49
|
+
_stateTargetChanged(target) {
|
|
50
|
+
if (target) {
|
|
51
|
+
this._ensureAttrsDelegated();
|
|
52
|
+
this._ensurePropsDelegated();
|
|
27
53
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** @protected */
|
|
57
|
+
_createDelegateAttrsObserver() {
|
|
58
|
+
this._createMethodObserver(`_delegateAttrsChanged(${this.constructor.delegateAttrs.join(', ')})`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** @protected */
|
|
62
|
+
_createDelegatePropsObserver() {
|
|
63
|
+
this._createMethodObserver(`_delegatePropsChanged(${this.constructor.delegateProps.join(', ')})`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** @protected */
|
|
67
|
+
_ensureAttrsDelegated() {
|
|
68
|
+
this.constructor.delegateAttrs.forEach((name) => {
|
|
69
|
+
this._delegateAttribute(name, this[name]);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** @protected */
|
|
74
|
+
_ensurePropsDelegated() {
|
|
75
|
+
this.constructor.delegateProps.forEach((name) => {
|
|
76
|
+
this._delegateProperty(name, this[name]);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** @protected */
|
|
81
|
+
_delegateAttrsChanged(...values) {
|
|
82
|
+
this.constructor.delegateAttrs.forEach((name, index) => {
|
|
83
|
+
this._delegateAttribute(name, values[index]);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** @protected */
|
|
88
|
+
_delegatePropsChanged(...values) {
|
|
89
|
+
this.constructor.delegateProps.forEach((name, index) => {
|
|
90
|
+
this._delegateProperty(name, values[index]);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** @protected */
|
|
95
|
+
_delegateAttribute(name, value) {
|
|
96
|
+
if (!this.stateTarget) {
|
|
97
|
+
return;
|
|
34
98
|
}
|
|
35
99
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
*/
|
|
39
|
-
static get delegateProps() {
|
|
40
|
-
return [];
|
|
100
|
+
if (name === 'invalid') {
|
|
101
|
+
this._delegateAttribute('aria-invalid', value ? 'true' : false);
|
|
41
102
|
}
|
|
42
103
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
this.
|
|
104
|
+
if (typeof value === 'boolean') {
|
|
105
|
+
this.stateTarget.toggleAttribute(name, value);
|
|
106
|
+
} else if (value) {
|
|
107
|
+
this.stateTarget.setAttribute(name, value);
|
|
108
|
+
} else {
|
|
109
|
+
this.stateTarget.removeAttribute(name);
|
|
49
110
|
}
|
|
111
|
+
}
|
|
50
112
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
this._ensurePropsDelegated();
|
|
56
|
-
}
|
|
113
|
+
/** @protected */
|
|
114
|
+
_delegateProperty(name, value) {
|
|
115
|
+
if (!this.stateTarget) {
|
|
116
|
+
return;
|
|
57
117
|
}
|
|
58
118
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
/** @protected */
|
|
65
|
-
_createDelegatePropsObserver() {
|
|
66
|
-
this._createMethodObserver(`_delegatePropsChanged(${this.constructor.delegateProps.join(', ')})`);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/** @protected */
|
|
70
|
-
_ensureAttrsDelegated() {
|
|
71
|
-
this.constructor.delegateAttrs.forEach((name) => {
|
|
72
|
-
this._delegateAttribute(name, this[name]);
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/** @protected */
|
|
77
|
-
_ensurePropsDelegated() {
|
|
78
|
-
this.constructor.delegateProps.forEach((name) => {
|
|
79
|
-
this._delegateProperty(name, this[name]);
|
|
80
|
-
});
|
|
81
|
-
}
|
|
119
|
+
this.stateTarget[name] = value;
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
};
|
|
82
123
|
|
|
83
|
-
|
|
84
|
-
_delegateAttrsChanged(...values) {
|
|
85
|
-
this.constructor.delegateAttrs.forEach((name, index) => {
|
|
86
|
-
this._delegateAttribute(name, values[index]);
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/** @protected */
|
|
91
|
-
_delegatePropsChanged(...values) {
|
|
92
|
-
this.constructor.delegateProps.forEach((name, index) => {
|
|
93
|
-
this._delegateProperty(name, values[index]);
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/** @protected */
|
|
98
|
-
_delegateAttribute(name, value) {
|
|
99
|
-
if (!this.stateTarget) {
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (name === 'invalid') {
|
|
104
|
-
this._delegateAttribute('aria-invalid', value ? 'true' : false);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (typeof value === 'boolean') {
|
|
108
|
-
this.stateTarget.toggleAttribute(name, value);
|
|
109
|
-
} else if (value) {
|
|
110
|
-
this.stateTarget.setAttribute(name, value);
|
|
111
|
-
} else {
|
|
112
|
-
this.stateTarget.removeAttribute(name);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/** @protected */
|
|
117
|
-
_delegateProperty(name, value) {
|
|
118
|
-
if (!this.stateTarget) {
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
this.stateTarget[name] = value;
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
);
|
|
124
|
+
export const DelegateStateMixin = dedupeMixin(DelegateStateMixinImplementation);
|
package/src/dir-mixin.js
CHANGED
|
@@ -33,8 +33,6 @@ directionObserver.observe(document.documentElement, { attributes: true, attribut
|
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
35
|
* A mixin to handle `dir` attribute based on the one set on the `<html>` element.
|
|
36
|
-
*
|
|
37
|
-
* @polymerMixin
|
|
38
36
|
*/
|
|
39
37
|
export const DirMixin = (superClass) =>
|
|
40
38
|
class VaadinDirMixin extends superClass {
|
package/src/element-mixin.js
CHANGED
package/src/gestures.js
CHANGED
|
@@ -121,7 +121,7 @@ function hasLeftMouseButton(ev) {
|
|
|
121
121
|
// instead we use ev.buttons (bitmask of buttons) or fall back to ev.which (deprecated, 0 for no buttons, 1 for left button)
|
|
122
122
|
if (type === 'mousemove') {
|
|
123
123
|
// Allow undefined for testing events
|
|
124
|
-
let buttons = ev.buttons
|
|
124
|
+
let buttons = ev.buttons ?? 1;
|
|
125
125
|
if (ev instanceof window.MouseEvent && !MOUSE_HAS_BUTTONS) {
|
|
126
126
|
buttons = MOUSE_WHICH_TO_BUTTONS[ev.which] || 0;
|
|
127
127
|
}
|
|
@@ -129,7 +129,7 @@ function hasLeftMouseButton(ev) {
|
|
|
129
129
|
return Boolean(buttons & 1);
|
|
130
130
|
}
|
|
131
131
|
// Allow undefined for testing events
|
|
132
|
-
const button = ev.button
|
|
132
|
+
const button = ev.button ?? 0;
|
|
133
133
|
// Ev.button is 0 in mousedown/mouseup/click for left button activation
|
|
134
134
|
return button === 0;
|
|
135
135
|
}
|
|
@@ -232,7 +232,7 @@ export function deepTargetFind(x, y) {
|
|
|
232
232
|
// This code path is only taken when native ShadowDOM is used
|
|
233
233
|
// if there is a shadowroot, it may have a node at x/y
|
|
234
234
|
// if there is not a shadowroot, exit the loop
|
|
235
|
-
while (next
|
|
235
|
+
while (next?.shadowRoot && !window.ShadyDOM) {
|
|
236
236
|
// If there is a node at x/y in the shadowroot, look deeper
|
|
237
237
|
const oldNext = next;
|
|
238
238
|
next = next.shadowRoot.elementFromPoint(x, y);
|
|
@@ -448,7 +448,7 @@ function _remove(node, evType, handler) {
|
|
|
448
448
|
for (let i = 0, dep, gd; i < deps.length; i++) {
|
|
449
449
|
dep = deps[i];
|
|
450
450
|
gd = gobj[dep];
|
|
451
|
-
if (gd
|
|
451
|
+
if (gd?.[name]) {
|
|
452
452
|
gd[name] = (gd[name] || 1) - 1;
|
|
453
453
|
gd._count = (gd._count || 1) - 1;
|
|
454
454
|
if (gd._count === 0) {
|
|
@@ -531,7 +531,7 @@ function _fire(target, type, detail) {
|
|
|
531
531
|
// Forward `preventDefault` in a clean way
|
|
532
532
|
if (ev.defaultPrevented) {
|
|
533
533
|
const preventer = detail.preventer || detail.sourceEvent;
|
|
534
|
-
if (preventer
|
|
534
|
+
if (preventer?.preventDefault) {
|
|
535
535
|
preventer.preventDefault();
|
|
536
536
|
}
|
|
537
537
|
}
|
package/src/i18n-mixin.d.ts
CHANGED
|
@@ -8,8 +8,7 @@ import type { Constructor } from '@open-wc/dedupe-mixin';
|
|
|
8
8
|
/**
|
|
9
9
|
* A mixin that allows to set partial I18N properties.
|
|
10
10
|
*/
|
|
11
|
-
export declare function I18nMixin<
|
|
12
|
-
defaultI18n: I,
|
|
11
|
+
export declare function I18nMixin<T extends Constructor<HTMLElement>, I = unknown>(
|
|
13
12
|
superclass: T,
|
|
14
13
|
): Constructor<I18nMixinClass<I>> & T;
|
|
15
14
|
|
package/src/i18n-mixin.js
CHANGED
|
@@ -35,9 +35,16 @@ function deepMerge(target, ...sources) {
|
|
|
35
35
|
/**
|
|
36
36
|
* A mixin that allows to set partial I18N properties.
|
|
37
37
|
*
|
|
38
|
-
*
|
|
38
|
+
* Subclasses provide their default values by overriding the
|
|
39
|
+
* `defaultI18n` static getter:
|
|
40
|
+
*
|
|
41
|
+
* ```js
|
|
42
|
+
* static get defaultI18n() {
|
|
43
|
+
* return { foo: 'Foo', bar: 'Bar' };
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
39
46
|
*/
|
|
40
|
-
export const I18nMixin = (
|
|
47
|
+
export const I18nMixin = (superClass) =>
|
|
41
48
|
class I18nMixinClass extends superClass {
|
|
42
49
|
static get properties() {
|
|
43
50
|
return {
|
|
@@ -55,10 +62,20 @@ export const I18nMixin = (defaultI18n, superClass) =>
|
|
|
55
62
|
};
|
|
56
63
|
}
|
|
57
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Default I18N values. Must be overridden by subclasses with actual defaults.
|
|
67
|
+
*
|
|
68
|
+
* @protected
|
|
69
|
+
* @return {Object}
|
|
70
|
+
*/
|
|
71
|
+
static get defaultI18n() {
|
|
72
|
+
return {};
|
|
73
|
+
}
|
|
74
|
+
|
|
58
75
|
constructor() {
|
|
59
76
|
super();
|
|
60
77
|
|
|
61
|
-
this.i18n = deepMerge({}, defaultI18n);
|
|
78
|
+
this.i18n = deepMerge({}, this.constructor.defaultI18n);
|
|
62
79
|
}
|
|
63
80
|
|
|
64
81
|
/**
|
|
@@ -80,6 +97,6 @@ export const I18nMixin = (defaultI18n, superClass) =>
|
|
|
80
97
|
return;
|
|
81
98
|
}
|
|
82
99
|
this.__customI18n = value;
|
|
83
|
-
this.__effectiveI18n = deepMerge({}, defaultI18n, this.__customI18n);
|
|
100
|
+
this.__effectiveI18n = deepMerge({}, this.constructor.defaultI18n, this.__customI18n);
|
|
84
101
|
}
|
|
85
102
|
};
|
|
@@ -7,8 +7,6 @@
|
|
|
7
7
|
/**
|
|
8
8
|
* A mixin that forwards CSS class names to the internal overlay element
|
|
9
9
|
* by setting the `overlayClass` property or `overlay-class` attribute.
|
|
10
|
-
*
|
|
11
|
-
* @polymerMixin
|
|
12
10
|
*/
|
|
13
11
|
export const OverlayClassMixin = (superclass) =>
|
|
14
12
|
class OverlayClassMixinClass extends superclass {
|
package/src/polylit-mixin.js
CHANGED
package/src/resize-mixin.js
CHANGED
|
@@ -26,69 +26,67 @@ const observer = new ResizeObserver((entries) => {
|
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* A mixin that uses a ResizeObserver to listen to host size changes.
|
|
29
|
-
*
|
|
30
|
-
* @polymerMixin
|
|
31
29
|
*/
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/** @protected */
|
|
46
|
-
connectedCallback() {
|
|
47
|
-
super.connectedCallback();
|
|
48
|
-
observer.observe(this);
|
|
30
|
+
const ResizeMixinImplementation = (superclass) =>
|
|
31
|
+
class ResizeMixinClass extends superclass {
|
|
32
|
+
/**
|
|
33
|
+
* When true, the parent element resize will be also observed.
|
|
34
|
+
* Override this getter and return `true` to enable this.
|
|
35
|
+
*
|
|
36
|
+
* @protected
|
|
37
|
+
*/
|
|
38
|
+
get _observeParent() {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
49
41
|
|
|
50
|
-
|
|
51
|
-
|
|
42
|
+
/** @protected */
|
|
43
|
+
connectedCallback() {
|
|
44
|
+
super.connectedCallback();
|
|
45
|
+
observer.observe(this);
|
|
52
46
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
observer.observe(parent);
|
|
56
|
-
}
|
|
47
|
+
if (this._observeParent) {
|
|
48
|
+
const parent = this.parentNode instanceof ShadowRoot ? this.parentNode.host : this.parentNode;
|
|
57
49
|
|
|
58
|
-
|
|
59
|
-
|
|
50
|
+
if (!parent.resizables) {
|
|
51
|
+
parent.resizables = new Set();
|
|
52
|
+
observer.observe(parent);
|
|
60
53
|
}
|
|
54
|
+
|
|
55
|
+
parent.resizables.add(this);
|
|
56
|
+
this.__parent = parent;
|
|
61
57
|
}
|
|
58
|
+
}
|
|
62
59
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
/** @protected */
|
|
61
|
+
disconnectedCallback() {
|
|
62
|
+
super.disconnectedCallback();
|
|
63
|
+
observer.unobserve(this);
|
|
67
64
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
const parent = this.__parent;
|
|
66
|
+
if (this._observeParent && parent) {
|
|
67
|
+
const resizables = parent.resizables;
|
|
71
68
|
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
if (resizables) {
|
|
70
|
+
resizables.delete(this);
|
|
74
71
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
72
|
+
if (resizables.size === 0) {
|
|
73
|
+
observer.unobserve(parent);
|
|
78
74
|
}
|
|
79
|
-
|
|
80
|
-
this.__parent = null;
|
|
81
75
|
}
|
|
82
|
-
}
|
|
83
76
|
|
|
84
|
-
|
|
85
|
-
* A handler invoked on host resize. By default, it does nothing.
|
|
86
|
-
* Override the method to implement your own behavior.
|
|
87
|
-
*
|
|
88
|
-
* @protected
|
|
89
|
-
*/
|
|
90
|
-
_onResize(_contentRect) {
|
|
91
|
-
// To be implemented.
|
|
77
|
+
this.__parent = null;
|
|
92
78
|
}
|
|
93
|
-
}
|
|
94
|
-
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* A handler invoked on host resize. By default, it does nothing.
|
|
83
|
+
* Override the method to implement your own behavior.
|
|
84
|
+
*
|
|
85
|
+
* @protected
|
|
86
|
+
*/
|
|
87
|
+
_onResize(_contentRect) {
|
|
88
|
+
// To be implemented.
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const ResizeMixin = dedupeMixin(ResizeMixinImplementation);
|
package/src/slot-controller.js
CHANGED
package/src/slot-observer.d.ts
CHANGED
|
@@ -5,15 +5,25 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* A helper for observing slot changes.
|
|
8
|
+
* A helper for observing slot or shadow-root changes.
|
|
9
|
+
*
|
|
10
|
+
* When `target` is an `HTMLSlotElement`, the observer listens for `slotchange`
|
|
11
|
+
* on the slot itself and diffs `target.assignedNodes({ flatten: true })`.
|
|
12
|
+
*
|
|
13
|
+
* When `target` is a `ShadowRoot`, the observer listens for `slotchange` events
|
|
14
|
+
* bubbling to it and diffs the **union** of `assignedNodes({ flatten: true })`
|
|
15
|
+
* every descendant `<slot>`. Cross-slot reassignment of the same node does
|
|
16
|
+
* not change the union and therefore fires no callback.
|
|
9
17
|
*/
|
|
10
18
|
export class SlotObserver {
|
|
11
19
|
constructor(
|
|
12
|
-
|
|
20
|
+
target: HTMLSlotElement | DocumentFragment,
|
|
13
21
|
callback: (info: { addedNodes: Node[]; currentNodes: Node[]; movedNodes: Node[]; removedNodes: Node[] }) => void,
|
|
14
22
|
forceInitial?: boolean,
|
|
15
23
|
);
|
|
16
24
|
|
|
25
|
+
readonly target: HTMLSlotElement | DocumentFragment;
|
|
26
|
+
|
|
17
27
|
/**
|
|
18
28
|
* Activates an observer. This method is automatically called when
|
|
19
29
|
* a `SlotObserver` is created. It should only be called to re-activate
|
package/src/slot-observer.js
CHANGED
|
@@ -5,22 +5,33 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* A helper for observing slot changes.
|
|
8
|
+
* A helper for observing slot or shadow-root changes.
|
|
9
|
+
*
|
|
10
|
+
* When `target` is an `HTMLSlotElement`, the observer listens for `slotchange`
|
|
11
|
+
* on the slot itself and diffs `target.assignedNodes({ flatten: true })`.
|
|
12
|
+
*
|
|
13
|
+
* When `target` is a `ShadowRoot`, the observer listens for `slotchange` events
|
|
14
|
+
* bubbling to it and diffs the **union** of `assignedNodes({ flatten: true })`
|
|
15
|
+
* across every descendant `<slot>`. Cross-slot reassignment of the same node
|
|
16
|
+
* does not change the union and therefore fires no callback.
|
|
9
17
|
*/
|
|
10
18
|
export class SlotObserver {
|
|
11
|
-
constructor(
|
|
12
|
-
/** @type HTMLSlotElement */
|
|
13
|
-
this.
|
|
19
|
+
constructor(target, callback, forceInitial) {
|
|
20
|
+
/** @type {HTMLSlotElement | DocumentFragment} */
|
|
21
|
+
this.target = target;
|
|
14
22
|
|
|
15
|
-
/** @type Function */
|
|
23
|
+
/** @type {Function} */
|
|
16
24
|
this.callback = callback;
|
|
17
25
|
|
|
18
|
-
/** @type boolean */
|
|
26
|
+
/** @type {boolean} */
|
|
19
27
|
this.forceInitial = forceInitial;
|
|
20
28
|
|
|
21
29
|
/** @type {Node[]} */
|
|
22
30
|
this._storedNodes = [];
|
|
23
31
|
|
|
32
|
+
/** @type {boolean} */
|
|
33
|
+
this._isSlot = target instanceof HTMLSlotElement;
|
|
34
|
+
|
|
24
35
|
this._connected = false;
|
|
25
36
|
this._scheduled = false;
|
|
26
37
|
|
|
@@ -38,7 +49,7 @@ export class SlotObserver {
|
|
|
38
49
|
* an observer that has been deactivated via the `disconnect` method.
|
|
39
50
|
*/
|
|
40
51
|
connect() {
|
|
41
|
-
this.
|
|
52
|
+
this.target.addEventListener('slotchange', this._boundSchedule);
|
|
42
53
|
this._connected = true;
|
|
43
54
|
}
|
|
44
55
|
|
|
@@ -48,7 +59,7 @@ export class SlotObserver {
|
|
|
48
59
|
* may be subsequently called to reactivate the observer.
|
|
49
60
|
*/
|
|
50
61
|
disconnect() {
|
|
51
|
-
this.
|
|
62
|
+
this.target.removeEventListener('slotchange', this._boundSchedule);
|
|
52
63
|
this._connected = false;
|
|
53
64
|
}
|
|
54
65
|
|
|
@@ -77,27 +88,56 @@ export class SlotObserver {
|
|
|
77
88
|
}
|
|
78
89
|
|
|
79
90
|
/** @private */
|
|
80
|
-
|
|
81
|
-
const
|
|
91
|
+
_collectNodes() {
|
|
92
|
+
const slots = this._isSlot ? [this.target] : [...this.target.querySelectorAll('slot')];
|
|
93
|
+
return [...new Set(slots.flatMap((slot) => slot.assignedNodes({ flatten: true })))];
|
|
94
|
+
}
|
|
82
95
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const
|
|
96
|
+
/** @private */
|
|
97
|
+
_groupNodesBySlot(nodes) {
|
|
98
|
+
const map = new Map();
|
|
99
|
+
nodes.forEach((node) => {
|
|
100
|
+
const slot = node.assignedSlot;
|
|
101
|
+
map.set(slot, map.get(slot) ?? []);
|
|
102
|
+
map.get(slot).push(node);
|
|
103
|
+
});
|
|
104
|
+
return map;
|
|
105
|
+
}
|
|
86
106
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
107
|
+
/**
|
|
108
|
+
* Collect moved nodes reordered within its current slot,
|
|
109
|
+
* but not those that are assigned to different slot.
|
|
110
|
+
*
|
|
111
|
+
* @private
|
|
112
|
+
*/
|
|
113
|
+
_collectMovedNodes(currentNodes) {
|
|
114
|
+
const currentPerSlot = this._groupNodesBySlot(currentNodes);
|
|
115
|
+
const storedPerSlot = this._groupNodesBySlot(this._storedNodes);
|
|
116
|
+
const movedNodes = [];
|
|
90
117
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
118
|
+
currentPerSlot.forEach((nodes, slot) => {
|
|
119
|
+
const stored = storedPerSlot.get(slot) || [];
|
|
120
|
+
// Skip slots whose membership changed: nodes entered or left the slot.
|
|
121
|
+
if (new Set(stored).difference(new Set(nodes)).size > 0) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
stored.forEach((node, storedIndex) => {
|
|
125
|
+
if (nodes.indexOf(node) !== storedIndex) {
|
|
97
126
|
movedNodes.push(node);
|
|
98
127
|
}
|
|
99
128
|
});
|
|
100
|
-
}
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
return movedNodes;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** @private */
|
|
135
|
+
_processNodes() {
|
|
136
|
+
const currentNodes = this._collectNodes();
|
|
137
|
+
|
|
138
|
+
const addedNodes = currentNodes.filter((node) => !this._storedNodes.includes(node));
|
|
139
|
+
const removedNodes = this._storedNodes.filter((node) => !currentNodes.includes(node));
|
|
140
|
+
const movedNodes = this._collectMovedNodes(currentNodes);
|
|
101
141
|
|
|
102
142
|
// By default, callback is not invoked if there is no child nodes in the slot.
|
|
103
143
|
// Use `forceInitial` flag if needed to also invoke it for the initial state.
|
package/src/slot-styles-mixin.js
CHANGED
|
@@ -39,38 +39,36 @@ function insertStyles(styles, root) {
|
|
|
39
39
|
/**
|
|
40
40
|
* Mixin to insert styles into the outer scope to handle slotted components.
|
|
41
41
|
* This is useful e.g. to hide native `<input type="number">` controls.
|
|
42
|
-
*
|
|
43
|
-
* @polymerMixin
|
|
44
42
|
*/
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
43
|
+
const SlotStylesMixinImplementation = (superclass) =>
|
|
44
|
+
class SlotStylesMixinClass extends superclass {
|
|
45
|
+
/**
|
|
46
|
+
* List of styles to insert into root.
|
|
47
|
+
* @protected
|
|
48
|
+
*/
|
|
49
|
+
get slotStyles() {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
55
52
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
/** @protected */
|
|
54
|
+
connectedCallback() {
|
|
55
|
+
super.connectedCallback();
|
|
59
56
|
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
this.__applySlotStyles();
|
|
58
|
+
}
|
|
62
59
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
/** @private */
|
|
61
|
+
__applySlotStyles() {
|
|
62
|
+
const root = this.getRootNode();
|
|
63
|
+
const rootStyles = getRootStyles(root);
|
|
67
64
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
65
|
+
this.slotStyles.forEach((styles) => {
|
|
66
|
+
if (!rootStyles.has(styles)) {
|
|
67
|
+
insertStyles(styles, root);
|
|
68
|
+
rootStyles.add(styles);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const SlotStylesMixin = dedupeMixin(SlotStylesMixinImplementation);
|
|
@@ -22,9 +22,7 @@ import { addGlobalStyles } from './add-global-styles.js';
|
|
|
22
22
|
name: propertyName,
|
|
23
23
|
syntax: '<color>',
|
|
24
24
|
inherits: true,
|
|
25
|
-
|
|
26
|
-
// is set to an invalid value to make debugging a bit easier.
|
|
27
|
-
initialValue: 'light-dark(black, white)',
|
|
25
|
+
initialValue: 'transparent',
|
|
28
26
|
});
|
|
29
27
|
});
|
|
30
28
|
|
|
@@ -86,6 +84,7 @@ addGlobalStyles(
|
|
|
86
84
|
--_vaadin-icon-calendar: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v4"/><path d="M16 2v4"/><rect width="18" height="18" x="3" y="4" rx="2"/><path d="M3 10h18"/></svg>');
|
|
87
85
|
--_vaadin-icon-checkmark: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" /></svg>');
|
|
88
86
|
--_vaadin-icon-chevron-down: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>');
|
|
87
|
+
--_vaadin-icon-chevron-right: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>');
|
|
89
88
|
--_vaadin-icon-clock: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 6v6l4 2"/><circle cx="12" cy="12" r="10"/></svg>');
|
|
90
89
|
--_vaadin-icon-cross: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" /></svg>');
|
|
91
90
|
--_vaadin-icon-drag: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"><path d="M11 7c0 .82843-.6716 1.5-1.5 1.5C8.67157 8.5 8 7.82843 8 7s.67157-1.5 1.5-1.5c.8284 0 1.5.67157 1.5 1.5Zm0 5c0 .8284-.6716 1.5-1.5 1.5-.82843 0-1.5-.6716-1.5-1.5s.67157-1.5 1.5-1.5c.8284 0 1.5.6716 1.5 1.5Zm0 5c0 .8284-.6716 1.5-1.5 1.5-.82843 0-1.5-.6716-1.5-1.5s.67157-1.5 1.5-1.5c.8284 0 1.5.6716 1.5 1.5Zm5-10c0 .82843-.6716 1.5-1.5 1.5S13 7.82843 13 7s.6716-1.5 1.5-1.5S16 6.17157 16 7Zm0 5c0 .8284-.6716 1.5-1.5 1.5S13 12.8284 13 12s.6716-1.5 1.5-1.5 1.5.6716 1.5 1.5Zm0 5c0 .8284-.6716 1.5-1.5 1.5S13 17.8284 13 17s.6716-1.5 1.5-1.5 1.5.6716 1.5 1.5Z" fill="currentColor"/></svg>');
|
|
@@ -23,6 +23,8 @@ type TooltipPosition =
|
|
|
23
23
|
* A controller that manages the slotted tooltip element.
|
|
24
24
|
*/
|
|
25
25
|
export class TooltipController extends SlotController {
|
|
26
|
+
constructor(host: HTMLElement);
|
|
27
|
+
|
|
26
28
|
/**
|
|
27
29
|
* An HTML element for linking with the tooltip overlay
|
|
28
30
|
* via `aria-describedby` attribute used by screen readers.
|
|
@@ -42,12 +44,6 @@ export class TooltipController extends SlotController {
|
|
|
42
44
|
*/
|
|
43
45
|
manual: boolean;
|
|
44
46
|
|
|
45
|
-
/**
|
|
46
|
-
* When true, the tooltip is opened programmatically.
|
|
47
|
-
* Only works if `manual` is set to `true`.
|
|
48
|
-
*/
|
|
49
|
-
opened: boolean;
|
|
50
|
-
|
|
51
47
|
/**
|
|
52
48
|
* Position of the tooltip with respect to its target.
|
|
53
49
|
*/
|
|
@@ -74,11 +70,6 @@ export class TooltipController extends SlotController {
|
|
|
74
70
|
*/
|
|
75
71
|
setManual(manual: boolean): void;
|
|
76
72
|
|
|
77
|
-
/**
|
|
78
|
-
* Toggle opened state on the slotted tooltip.
|
|
79
|
-
*/
|
|
80
|
-
setOpened(opened: boolean): void;
|
|
81
|
-
|
|
82
73
|
/**
|
|
83
74
|
* Set default position for the slotted tooltip.
|
|
84
75
|
* This can be overridden by setting the position
|
|
@@ -96,4 +87,18 @@ export class TooltipController extends SlotController {
|
|
|
96
87
|
* Set an HTML element to attach the tooltip to.
|
|
97
88
|
*/
|
|
98
89
|
setTarget(target: HTMLElement): void;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Schedule opening the slotted tooltip. Respects the tooltip's
|
|
93
|
+
* configured `hoverDelay` / `focusDelay` and the shared warm-up state.
|
|
94
|
+
* No-op when no tooltip is slotted.
|
|
95
|
+
*/
|
|
96
|
+
open(options?: { hover?: boolean; focus?: boolean; immediate?: boolean }): void;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Schedule closing the slotted tooltip. Respects the tooltip's
|
|
100
|
+
* configured `hideDelay` unless `immediate` is true.
|
|
101
|
+
* No-op when no tooltip is slotted.
|
|
102
|
+
*/
|
|
103
|
+
close(immediate?: boolean): void;
|
|
99
104
|
}
|
|
@@ -39,10 +39,6 @@ export class TooltipController extends SlotController {
|
|
|
39
39
|
tooltipNode.manual = this.manual;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
if (this.opened !== undefined) {
|
|
43
|
-
tooltipNode.opened = this.opened;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
42
|
if (this.position !== undefined) {
|
|
47
43
|
tooltipNode._position = this.position;
|
|
48
44
|
}
|
|
@@ -113,19 +109,6 @@ export class TooltipController extends SlotController {
|
|
|
113
109
|
}
|
|
114
110
|
}
|
|
115
111
|
|
|
116
|
-
/**
|
|
117
|
-
* Toggle opened state on the slotted tooltip.
|
|
118
|
-
* @param {boolean} opened
|
|
119
|
-
*/
|
|
120
|
-
setOpened(opened) {
|
|
121
|
-
this.opened = opened;
|
|
122
|
-
|
|
123
|
-
const tooltipNode = this.node;
|
|
124
|
-
if (tooltipNode) {
|
|
125
|
-
tooltipNode.opened = opened;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
112
|
/**
|
|
130
113
|
* Set default position for the slotted tooltip.
|
|
131
114
|
* This can be overridden by setting the position
|
|
@@ -168,6 +151,34 @@ export class TooltipController extends SlotController {
|
|
|
168
151
|
}
|
|
169
152
|
}
|
|
170
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Schedule opening the slotted tooltip. Respects the tooltip's
|
|
156
|
+
* configured `hoverDelay` / `focusDelay` and the shared warm-up state.
|
|
157
|
+
* No-op when no tooltip is slotted.
|
|
158
|
+
*
|
|
159
|
+
* @param {{ hover?: boolean, focus?: boolean, immediate?: boolean }} [options]
|
|
160
|
+
*/
|
|
161
|
+
open(options) {
|
|
162
|
+
const tooltipNode = this.node;
|
|
163
|
+
if (tooltipNode?.isConnected) {
|
|
164
|
+
tooltipNode._stateController.open(options);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Schedule closing the slotted tooltip. Respects the tooltip's
|
|
170
|
+
* configured `hideDelay` unless `immediate` is true.
|
|
171
|
+
* No-op when no tooltip is slotted.
|
|
172
|
+
*
|
|
173
|
+
* @param {boolean} [immediate]
|
|
174
|
+
*/
|
|
175
|
+
close(immediate) {
|
|
176
|
+
const tooltipNode = this.node;
|
|
177
|
+
if (tooltipNode) {
|
|
178
|
+
tooltipNode._stateController.close(immediate);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
171
182
|
/** @private */
|
|
172
183
|
__onContentChange(event) {
|
|
173
184
|
this.__notifyChange(event.target);
|
|
@@ -515,11 +515,19 @@ export class IronListAdapter {
|
|
|
515
515
|
|
|
516
516
|
/** @private */
|
|
517
517
|
__getFocusedElement(visibleElements = this.__getVisibleElements()) {
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
518
|
+
// `document.activeElement` retargets to the outermost shadow host when
|
|
519
|
+
// focus lives in a nested shadow tree. Descend through nested shadow
|
|
520
|
+
// roots' `activeElement`s to reach the real focused node, then walk up
|
|
521
|
+
// the flattened tree (via `assignedSlot`/`parentNode`/`host`) until a
|
|
522
|
+
// visible row is reached.
|
|
523
|
+
let node = document.activeElement;
|
|
524
|
+
while (node?.shadowRoot?.activeElement) {
|
|
525
|
+
node = node.shadowRoot.activeElement;
|
|
526
|
+
}
|
|
527
|
+
while (node && !visibleElements.includes(node)) {
|
|
528
|
+
node = node.assignedSlot || node.parentNode || node.host;
|
|
529
|
+
}
|
|
530
|
+
return node;
|
|
523
531
|
}
|
|
524
532
|
|
|
525
533
|
/** @private */
|