@vaadin/vaadin-themable-mixin 25.0.0-alpha6 → 25.0.0-alpha8
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/lumo-injection-mixin.js +6 -0
- package/package.json +4 -4
- package/src/css-property-observer.js +36 -12
- package/src/css-utils.js +9 -15
- package/src/lumo-injector.js +40 -10
package/lumo-injection-mixin.js
CHANGED
|
@@ -61,6 +61,12 @@ export const LumoInjectionMixin = (superClass) =>
|
|
|
61
61
|
return `--${this.is}-lumo-inject`;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
static get lumoInjector() {
|
|
65
|
+
return {
|
|
66
|
+
includeBaseStyles: false,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
64
70
|
/** @protected */
|
|
65
71
|
connectedCallback() {
|
|
66
72
|
super.connectedCallback();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/vaadin-themable-mixin",
|
|
3
|
-
"version": "25.0.0-
|
|
3
|
+
"version": "25.0.0-alpha8",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -37,10 +37,10 @@
|
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@polymer/polymer": "^3.0.0",
|
|
40
|
-
"@vaadin/chai-plugins": "25.0.0-
|
|
41
|
-
"@vaadin/test-runner-commands": "25.0.0-
|
|
40
|
+
"@vaadin/chai-plugins": "25.0.0-alpha8",
|
|
41
|
+
"@vaadin/test-runner-commands": "25.0.0-alpha8",
|
|
42
42
|
"@vaadin/testing-helpers": "^2.0.0",
|
|
43
43
|
"sinon": "^18.0.0"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "ebf53673d5f639d2b1b6f2b31f640f530643ee2f"
|
|
46
46
|
}
|
|
@@ -14,14 +14,36 @@ export class CSSPropertyObserver {
|
|
|
14
14
|
#name;
|
|
15
15
|
#callback;
|
|
16
16
|
#properties = new Set();
|
|
17
|
+
#styleSheet;
|
|
18
|
+
#isConnected = false;
|
|
17
19
|
|
|
18
20
|
constructor(root, name, callback) {
|
|
19
21
|
this.#root = root;
|
|
20
22
|
this.#name = name;
|
|
21
23
|
this.#callback = callback;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
#handleTransitionEvent(event) {
|
|
27
|
+
const { propertyName } = event;
|
|
28
|
+
if (this.#properties.has(propertyName)) {
|
|
29
|
+
this.#callback(propertyName);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
observe(property) {
|
|
34
|
+
this.connect();
|
|
35
|
+
|
|
36
|
+
this.#properties.add(property);
|
|
37
|
+
this.#rootHost.style.setProperty(`--${this.#name}-props`, [...this.#properties].join(', '));
|
|
38
|
+
}
|
|
22
39
|
|
|
23
|
-
|
|
24
|
-
|
|
40
|
+
connect() {
|
|
41
|
+
if (this.#isConnected) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
this.#styleSheet = new CSSStyleSheet();
|
|
46
|
+
this.#styleSheet.replaceSync(`
|
|
25
47
|
:is(:root, :host)::before {
|
|
26
48
|
content: '' !important;
|
|
27
49
|
position: absolute !important;
|
|
@@ -32,22 +54,24 @@ export class CSSPropertyObserver {
|
|
|
32
54
|
transition-property: var(--${this.#name}-props) !important;
|
|
33
55
|
}
|
|
34
56
|
`);
|
|
35
|
-
this.#root.adoptedStyleSheets.unshift(styleSheet);
|
|
57
|
+
this.#root.adoptedStyleSheets.unshift(this.#styleSheet);
|
|
36
58
|
|
|
37
59
|
this.#rootHost.addEventListener('transitionstart', (event) => this.#handleTransitionEvent(event));
|
|
38
60
|
this.#rootHost.addEventListener('transitionend', (event) => this.#handleTransitionEvent(event));
|
|
39
|
-
}
|
|
40
61
|
|
|
41
|
-
|
|
42
|
-
const { propertyName } = event;
|
|
43
|
-
if (this.#properties.has(propertyName)) {
|
|
44
|
-
this.#callback(propertyName);
|
|
45
|
-
}
|
|
62
|
+
this.#isConnected = true;
|
|
46
63
|
}
|
|
47
64
|
|
|
48
|
-
|
|
49
|
-
this.#properties.
|
|
50
|
-
|
|
65
|
+
disconnect() {
|
|
66
|
+
this.#properties.clear();
|
|
67
|
+
|
|
68
|
+
this.#root.adoptedStyleSheets = this.#root.adoptedStyleSheets.filter((s) => s !== this.#styleSheet);
|
|
69
|
+
|
|
70
|
+
this.#rootHost.removeEventListener('transitionstart', this.#handleTransitionEvent);
|
|
71
|
+
this.#rootHost.removeEventListener('transitionend', this.#handleTransitionEvent);
|
|
72
|
+
this.#rootHost.style.removeProperty(`--${this.#name}-props`);
|
|
73
|
+
|
|
74
|
+
this.#isConnected = false;
|
|
51
75
|
}
|
|
52
76
|
|
|
53
77
|
get #rootHost() {
|
package/src/css-utils.js
CHANGED
|
@@ -15,16 +15,14 @@ import { adoptStyles } from 'lit';
|
|
|
15
15
|
* @return {CSSStyleSheet[]}
|
|
16
16
|
*/
|
|
17
17
|
function getEffectiveStyles(component) {
|
|
18
|
-
const
|
|
18
|
+
const { baseStyles, themeStyles, elementStyles, lumoInjector } = component.constructor;
|
|
19
|
+
const lumoStyleSheet = component.__lumoStyleSheet;
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return (componentClass.baseStyles ?? componentClass.themeStyles)
|
|
23
|
-
? [...componentClass.baseStyles, styleSheet, ...componentClass.themeStyles]
|
|
24
|
-
: [styleSheet, ...componentClass.elementStyles];
|
|
21
|
+
if (lumoStyleSheet && (baseStyles || themeStyles)) {
|
|
22
|
+
return [...(lumoInjector.includeBaseStyles ? baseStyles : []), lumoStyleSheet, ...themeStyles];
|
|
25
23
|
}
|
|
26
24
|
|
|
27
|
-
return
|
|
25
|
+
return [lumoStyleSheet, ...elementStyles].filter(Boolean);
|
|
28
26
|
}
|
|
29
27
|
|
|
30
28
|
/**
|
|
@@ -47,7 +45,7 @@ export function applyInstanceStyles(component) {
|
|
|
47
45
|
*/
|
|
48
46
|
export function injectLumoStyleSheet(component, styleSheet) {
|
|
49
47
|
// Store the new stylesheet so that it can be removed later.
|
|
50
|
-
component.
|
|
48
|
+
component.__lumoStyleSheet = styleSheet;
|
|
51
49
|
applyInstanceStyles(component);
|
|
52
50
|
}
|
|
53
51
|
|
|
@@ -57,11 +55,7 @@ export function injectLumoStyleSheet(component, styleSheet) {
|
|
|
57
55
|
*
|
|
58
56
|
* @param {HTMLElement} component
|
|
59
57
|
*/
|
|
60
|
-
export function
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
component.shadowRoot.adoptedStyleSheets = adoptedStyleSheets;
|
|
66
|
-
component.__lumoInjectorStyleSheet = undefined;
|
|
58
|
+
export function removeLumoStyleSheet(component) {
|
|
59
|
+
component.__lumoStyleSheet = undefined;
|
|
60
|
+
applyInstanceStyles(component);
|
|
67
61
|
}
|
package/src/lumo-injector.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
6
|
import { CSSPropertyObserver } from './css-property-observer.js';
|
|
7
|
-
import {
|
|
7
|
+
import { injectLumoStyleSheet, removeLumoStyleSheet } from './css-utils.js';
|
|
8
8
|
import { parseStyleSheets } from './lumo-modules.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -77,14 +77,23 @@ export class LumoInjector {
|
|
|
77
77
|
/** @type {Map<string, CSSStyleSheet>} */
|
|
78
78
|
#styleSheetsByTag = new Map();
|
|
79
79
|
|
|
80
|
+
/** @type {Map<string, Set<HTMLElement>>} */
|
|
81
|
+
#componentsByTag = new Map();
|
|
82
|
+
|
|
80
83
|
constructor(root = document) {
|
|
81
84
|
this.#root = root;
|
|
82
85
|
this.#cssPropertyObserver = new CSSPropertyObserver(this.#root, 'vaadin-lumo-injector', (propertyName) => {
|
|
83
86
|
const tagName = propertyName.slice(2).replace('-lumo-inject', '');
|
|
84
|
-
this.#
|
|
87
|
+
this.#updateStyleSheet(tagName);
|
|
85
88
|
});
|
|
86
89
|
}
|
|
87
90
|
|
|
91
|
+
disconnect() {
|
|
92
|
+
this.#cssPropertyObserver.disconnect();
|
|
93
|
+
this.#styleSheetsByTag.clear();
|
|
94
|
+
this.#componentsByTag.values().forEach((components) => components.forEach(removeLumoStyleSheet));
|
|
95
|
+
}
|
|
96
|
+
|
|
88
97
|
/**
|
|
89
98
|
* Adds a component to the list of elements monitored for style injection.
|
|
90
99
|
* If the styles have already been detected, they are injected into the
|
|
@@ -97,12 +106,18 @@ export class LumoInjector {
|
|
|
97
106
|
componentConnected(component) {
|
|
98
107
|
const { is: tagName, lumoInjectPropName } = component.constructor;
|
|
99
108
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
this.#styleSheetsByTag.set(tagName, stylesheet);
|
|
109
|
+
this.#componentsByTag.set(tagName, this.#componentsByTag.get(tagName) ?? new Set());
|
|
110
|
+
this.#componentsByTag.get(tagName).add(component);
|
|
103
111
|
|
|
104
|
-
this.#
|
|
112
|
+
const stylesheet = this.#styleSheetsByTag.get(tagName);
|
|
113
|
+
if (stylesheet) {
|
|
114
|
+
if (stylesheet.cssRules.length > 0) {
|
|
115
|
+
injectLumoStyleSheet(component, stylesheet);
|
|
116
|
+
}
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
105
119
|
|
|
120
|
+
this.#initStyleSheet(tagName);
|
|
106
121
|
this.#cssPropertyObserver.observe(lumoInjectPropName);
|
|
107
122
|
}
|
|
108
123
|
|
|
@@ -113,10 +128,18 @@ export class LumoInjector {
|
|
|
113
128
|
* @param {HTMLElement} component
|
|
114
129
|
*/
|
|
115
130
|
componentDisconnected(component) {
|
|
116
|
-
|
|
131
|
+
const { is: tagName } = component.constructor;
|
|
132
|
+
this.#componentsByTag.get(tagName)?.delete(component);
|
|
133
|
+
|
|
134
|
+
removeLumoStyleSheet(component);
|
|
117
135
|
}
|
|
118
136
|
|
|
119
|
-
#
|
|
137
|
+
#initStyleSheet(tagName) {
|
|
138
|
+
this.#styleSheetsByTag.set(tagName, new CSSStyleSheet());
|
|
139
|
+
this.#updateStyleSheet(tagName);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
#updateStyleSheet(tagName) {
|
|
120
143
|
const { tags, modules } = parseStyleSheets(this.#rootStyleSheets);
|
|
121
144
|
|
|
122
145
|
const cssText = (tags.get(tagName) ?? [])
|
|
@@ -124,9 +147,16 @@ export class LumoInjector {
|
|
|
124
147
|
.map((rule) => rule.cssText)
|
|
125
148
|
.join('\n');
|
|
126
149
|
|
|
127
|
-
const stylesheet = this.#styleSheetsByTag.get(tagName)
|
|
150
|
+
const stylesheet = this.#styleSheetsByTag.get(tagName);
|
|
128
151
|
stylesheet.replaceSync(cssText);
|
|
129
|
-
|
|
152
|
+
|
|
153
|
+
this.#componentsByTag.get(tagName)?.forEach((component) => {
|
|
154
|
+
if (cssText) {
|
|
155
|
+
injectLumoStyleSheet(component, stylesheet);
|
|
156
|
+
} else {
|
|
157
|
+
removeLumoStyleSheet(component);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
130
160
|
}
|
|
131
161
|
|
|
132
162
|
get #rootStyleSheets() {
|