Skip to content

Commit 7b54b9b

Browse files
authored
feat(framework): Make addCustomCSS dynamic (#2083)
1 parent 974401b commit 7b54b9b

9 files changed

+135
-34
lines changed

packages/base/src/RenderScheduler.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -142,18 +142,21 @@ class RenderScheduler {
142142
*
143143
* Usage:
144144
* reRenderAllUI5Elements() -> rerenders all components
145+
* reRenderAllUI5Elements({tag: "ui5-button"}) -> re-renders only instances of ui5-button
145146
* reRenderAllUI5Elements({rtlAware: true}) -> re-renders only rtlAware components
146147
* reRenderAllUI5Elements({languageAware: true}) -> re-renders only languageAware components
147148
* reRenderAllUI5Elements({rtlAware: true, languageAware: true}) -> re-renders components that are rtlAware or languageAware
149+
* etc...
148150
*
149151
* @public
150152
* @param {Object|undefined} filters - Object with keys that can be "rtlAware" or "languageAware"
151153
*/
152154
static reRenderAllUI5Elements(filters) {
153155
registeredElements.forEach(element => {
156+
const tag = element.constructor.getMetadata().getTag();
154157
const rtlAware = isRtlAware(element.constructor);
155158
const languageAware = element.constructor.getMetadata().isLanguageAware();
156-
if (!filters || (filters.rtlAware && rtlAware) || (filters.languageAware && languageAware)) {
159+
if (!filters || (filters.tag === tag) || (filters.rtlAware && rtlAware) || (filters.languageAware && languageAware)) {
157160
RenderScheduler.renderDeferred(element);
158161
}
159162
});

packages/base/src/UI5Element.js

+12-11
Original file line numberDiff line numberDiff line change
@@ -85,17 +85,6 @@ class UI5Element extends HTMLElement {
8585
// Init Shadow Root
8686
if (needsShadowDOM) {
8787
this.attachShadow({ mode: "open" });
88-
89-
// IE11, Edge
90-
if (window.ShadyDOM) {
91-
createComponentStyleTag(this.constructor);
92-
}
93-
94-
// Chrome
95-
if (document.adoptedStyleSheets) {
96-
const style = getConstructableStyle(this.constructor);
97-
this.shadowRoot.adoptedStyleSheets = [style];
98-
}
9988
}
10089

10190
// Init StaticAreaItem only if needed
@@ -562,9 +551,21 @@ class UI5Element extends HTMLElement {
562551
let styleToPrepend;
563552
const renderResult = this.constructor.template(this);
564553

554+
// IE11, Edge
555+
if (window.ShadyDOM) {
556+
createComponentStyleTag(this.constructor);
557+
}
558+
559+
// Chrome
560+
if (document.adoptedStyleSheets) {
561+
this.shadowRoot.adoptedStyleSheets = getConstructableStyle(this.constructor);
562+
}
563+
564+
// FF, Safari
565565
if (!document.adoptedStyleSheets && !window.ShadyDOM) {
566566
styleToPrepend = getEffectiveStyle(this.constructor);
567567
}
568+
568569
this.constructor.render(renderResult, this.shadowRoot, styleToPrepend, { eventContext: this });
569570
}
570571

+28-7
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,40 @@
1-
const customCSSFor = {};
1+
import RenderScheduler from "../RenderScheduler.js";
2+
import EventProvider from "../EventProvider.js";
23

3-
const addCustomCSS = (tag, css, ...rest) => {
4-
if (rest.length) {
5-
throw new Error("addCustomCSS no longer accepts theme specific CSS. new signature is `addCustomCSS(tag, css)`");
6-
}
4+
const eventProvider = new EventProvider();
5+
const CUSTOM_CSS_CHANGE = "CustomCSSChange";
6+
7+
const attachCustomCSSChange = listener => {
8+
eventProvider.attachEvent(CUSTOM_CSS_CHANGE, listener);
9+
};
710

11+
const detachCustomCSSChange = listener => {
12+
eventProvider.detachEvent(CUSTOM_CSS_CHANGE, listener);
13+
};
14+
15+
const fireCustomCSSChange = tag => {
16+
return eventProvider.fireEvent(CUSTOM_CSS_CHANGE, tag);
17+
};
18+
19+
const customCSSFor = {};
20+
21+
const addCustomCSS = (tag, css) => {
822
if (!customCSSFor[tag]) {
923
customCSSFor[tag] = [];
1024
}
11-
1225
customCSSFor[tag].push(css);
26+
fireCustomCSSChange(tag);
27+
28+
RenderScheduler.reRenderAllUI5Elements({ tag });
1329
};
1430

1531
const getCustomCSS = tag => {
1632
return customCSSFor[tag] ? customCSSFor[tag].join("") : "";
1733
};
1834

19-
export { addCustomCSS, getCustomCSS };
35+
export {
36+
addCustomCSS,
37+
getCustomCSS,
38+
attachCustomCSSChange,
39+
detachCustomCSSChange,
40+
};

packages/base/src/theming/createComponentStyleTag.js

+5
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@ import createStyleInHead from "../util/createStyleInHead.js";
22
import getEffectiveStyle from "./getEffectiveStyle.js";
33
import adaptCSSForIE from "./adaptCSSForIE.js";
44
import { ponyfillNeeded, schedulePonyfill } from "./CSSVarsPonyfill.js";
5+
import { attachCustomCSSChange } from "./CustomStyle.js";
56

67
const IEStyleSet = new Set();
78

9+
attachCustomCSSChange(tag => {
10+
IEStyleSet.delete(tag);
11+
});
12+
813
const getStaticStyle = ElementClass => {
914
let componentStaticStyles = ElementClass.staticAreaStyles;
1015
if (Array.isArray(componentStaticStyles)) {
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,29 @@
11
import getEffectiveStyle from "./getEffectiveStyle.js";
2+
import { attachCustomCSSChange } from "./CustomStyle.js";
23

34
const constructableStyleMap = new Map();
45

6+
attachCustomCSSChange(tag => {
7+
constructableStyleMap.delete(tag);
8+
});
9+
510
/**
611
* Returns (and caches) a constructable style sheet for a web component class
712
* Note: Chrome
813
* @param ElementClass
914
* @returns {*}
1015
*/
1116
const getConstructableStyle = ElementClass => {
12-
const tagName = ElementClass.getMetadata().getTag();
13-
const styleContent = getEffectiveStyle(ElementClass);
14-
if (constructableStyleMap.has(tagName)) {
15-
return constructableStyleMap.get(tagName);
16-
}
17+
const tag = ElementClass.getMetadata().getTag();
1718

18-
const style = new CSSStyleSheet();
19-
style.replaceSync(styleContent);
19+
if (!constructableStyleMap.has(tag)) {
20+
const styleContent = getEffectiveStyle(ElementClass);
21+
const style = new CSSStyleSheet();
22+
style.replaceSync(styleContent);
23+
constructableStyleMap.set(tag, [style]);
24+
}
2025

21-
constructableStyleMap.set(tagName, style);
22-
return style;
26+
return constructableStyleMap.get(tag);
2327
};
2428

2529
export default getConstructableStyle;
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
1-
import { getCustomCSS } from "./CustomStyle.js";
1+
import { getCustomCSS, attachCustomCSSChange } from "./CustomStyle.js";
22
import getStylesString from "./getStylesString.js";
33

4+
const effectiveStyleMap = new Map();
5+
6+
attachCustomCSSChange(tag => {
7+
effectiveStyleMap.delete(tag);
8+
});
9+
410
const getEffectiveStyle = ElementClass => {
511
const tag = ElementClass.getMetadata().getTag();
6-
const customStyle = getCustomCSS(tag) || "";
712

8-
const builtInStyles = getStylesString(ElementClass.styles);
9-
return `${builtInStyles} ${customStyle}`;
13+
if (!effectiveStyleMap.has(tag)) {
14+
const customStyle = getCustomCSS(tag) || "";
15+
const builtInStyles = getStylesString(ElementClass.styles);
16+
const effectiveStyle = `${builtInStyles} ${customStyle}`;
17+
effectiveStyleMap.set(tag, effectiveStyle);
18+
}
19+
20+
return effectiveStyleMap.get(tag);
1021
};
1122

1223
export default getEffectiveStyle;

packages/main/bundle.es5.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import { getFirstDayOfWeek } from "@ui5/webcomponents-base/dist/config/FormatSet
1212
import { getRegisteredNames as getIconNames } from "@ui5/webcomponents-base/dist/SVGIconRegistry.js";
1313
import applyDirection from "@ui5/webcomponents-base/dist/locale/applyDirection.js";
1414
import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js";
15+
import { addCustomCSS } from "@ui5/webcomponents-base/dist/Theming.js";
16+
1517
const configuration = {
1618
getAnimationMode,
1719
setAnimationMode,
@@ -25,7 +27,7 @@ const configuration = {
2527
};
2628
export {
2729
configuration,
28-
getIconNames,
2930
applyDirection,
3031
ResizeHandler,
32+
addCustomCSS,
3133
};

packages/main/bundle.esm.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ import { getFirstDayOfWeek } from "@ui5/webcomponents-base/dist/config/FormatSet
9797
import { getRegisteredNames as getIconNames } from "@ui5/webcomponents-base/dist/SVGIconRegistry.js";
9898
import applyDirection from "@ui5/webcomponents-base/dist/locale/applyDirection.js";
9999
import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js";
100+
import { addCustomCSS } from "@ui5/webcomponents-base/dist/Theming";
100101
window["sap-ui-webcomponents-bundle"] = {
101102
configuration : {
102103
getAnimationMode,
@@ -109,8 +110,8 @@ window["sap-ui-webcomponents-bundle"] = {
109110
getRTL,
110111
getFirstDayOfWeek,
111112
},
112-
getIconNames,
113113
getLocaleData,
114114
applyDirection,
115115
ResizeHandler,
116+
addCustomCSS,
116117
};
+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6+
<meta charset="utf-8">
7+
8+
<title>Button</title>
9+
10+
<script data-ui5-config type="application/json">
11+
{
12+
"language": "EN",
13+
"noConflict": {
14+
"events": ["click"]
15+
},
16+
"calendarType": "Islamic"
17+
}
18+
</script>
19+
20+
<script src="../../webcomponentsjs/webcomponents-loader.js"></script>
21+
<script src="../../resources/bundle.esm.js" type="module"></script>
22+
<script nomodule src="../../resources/bundle.es5.js"></script>
23+
24+
</head>
25+
26+
<body style="background-color: var(--sapBackgroundColor);">
27+
28+
<ui5-select id="select">
29+
<ui5-option>1</ui5-option>
30+
<ui5-option>2</ui5-option>
31+
</ui5-select>
32+
33+
<br />
34+
<br />
35+
36+
<ui5-button id="btn">Apply custom css and rerender</ui5-button>
37+
38+
<br />
39+
<br />
40+
41+
<script>
42+
const applyCustomCSSAndRerender = function() {
43+
window["sap-ui-webcomponents-bundle"].addCustomCSS("ui5-select", ".ui5-select-root { background-color: red; } ");
44+
};
45+
46+
document
47+
.getElementById("btn")
48+
.addEventListener("click", applyCustomCSSAndRerender);
49+
50+
</script>
51+
52+
</body>
53+
</html>

0 commit comments

Comments
 (0)