@ui5/webcomponents-base 0.0.0-db2be6526 → 0.0.0-dc3ccac50

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.
Files changed (53) hide show
  1. package/dist/CSP.js +59 -0
  2. package/dist/FontFace.js +2 -102
  3. package/dist/ManagedStyles.js +52 -5
  4. package/dist/Render.js +3 -1
  5. package/dist/StaticAreaItem.js +0 -9
  6. package/dist/SystemCSSVars.js +1 -20
  7. package/dist/UI5Element.js +13 -21
  8. package/dist/UI5ElementMetadata.js +8 -0
  9. package/dist/asset-registries/Icons.js +25 -14
  10. package/dist/assets-meta/IconCollectionsAlias.js +18 -0
  11. package/dist/config/Theme.js +14 -0
  12. package/dist/css/FontFace.css +45 -0
  13. package/dist/css/OverrideFontFace.css +32 -0
  14. package/dist/css/SystemCSSVars.css +17 -0
  15. package/dist/generated/css/FontFace.css.js +5 -0
  16. package/dist/generated/css/OverrideFontFace.css.js +5 -0
  17. package/dist/generated/css/SystemCSSVars.css.js +5 -0
  18. package/dist/renderer/LitRenderer.js +5 -3
  19. package/dist/resources/bundle.esm.js +8 -8
  20. package/dist/resources/bundle.esm.js.map +1 -1
  21. package/dist/theming/applyTheme.js +4 -7
  22. package/dist/theming/getEffectiveLinksHrefs.js +20 -0
  23. package/dist/theming/getStylesString.js +4 -2
  24. package/dist/theming/preloadLinks.js +23 -0
  25. package/dist/updateShadowRoot.js +8 -4
  26. package/dist/util/createLinkInHead.js +19 -0
  27. package/hash.txt +1 -1
  28. package/lib/generate-styles/index.js +18 -0
  29. package/package-scripts.js +6 -3
  30. package/package.json +4 -3
  31. package/src/CSP.js +59 -0
  32. package/src/FontFace.js +2 -102
  33. package/src/ManagedStyles.js +52 -5
  34. package/src/Render.js +3 -1
  35. package/src/StaticAreaItem.js +0 -9
  36. package/src/SystemCSSVars.js +1 -20
  37. package/src/UI5Element.js +13 -21
  38. package/src/UI5ElementMetadata.js +8 -0
  39. package/src/asset-registries/Icons.js +25 -14
  40. package/src/assets-meta/IconCollectionsAlias.js +18 -0
  41. package/src/config/Theme.js +14 -0
  42. package/src/css/FontFace.css +45 -0
  43. package/src/css/OverrideFontFace.css +32 -0
  44. package/src/css/SystemCSSVars.css +17 -0
  45. package/src/renderer/LitRenderer.js +5 -3
  46. package/src/theming/applyTheme.js +4 -7
  47. package/src/theming/getEffectiveLinksHrefs.js +20 -0
  48. package/src/theming/getStylesString.js +4 -2
  49. package/src/theming/preloadLinks.js +23 -0
  50. package/src/updateShadowRoot.js +8 -4
  51. package/src/util/createLinkInHead.js +19 -0
  52. package/dist/theming/createThemePropertiesStyleTag.js +0 -16
  53. package/src/theming/createThemePropertiesStyleTag.js +0 -16
@@ -1,5 +1,5 @@
1
1
  import { getThemeProperties, getRegisteredPackages, isThemeRegistered } from "../asset-registries/Themes.js";
2
- import createThemePropertiesStyleTag from "./createThemePropertiesStyleTag.js";
2
+ import { removeStyle, createOrUpdateStyle } from "../ManagedStyles.js";
3
3
  import getThemeDesignerTheme from "./getThemeDesignerTheme.js";
4
4
  import { fireThemeLoaded } from "./ThemeLoaded.js";
5
5
  import { getFeature } from "../FeaturesRegistry.js";
@@ -17,14 +17,11 @@ const loadThemeBase = async theme => {
17
17
  }
18
18
 
19
19
  const cssText = await getThemeProperties(BASE_THEME_PACKAGE, theme);
20
- createThemePropertiesStyleTag(cssText, BASE_THEME_PACKAGE);
20
+ createOrUpdateStyle(cssText, "data-ui5-theme-properties", BASE_THEME_PACKAGE);
21
21
  };
22
22
 
23
23
  const deleteThemeBase = () => {
24
- const styleElement = document.head.querySelector(`style[data-ui5-theme-properties="${BASE_THEME_PACKAGE}"]`);
25
- if (styleElement) {
26
- styleElement.parentElement.removeChild(styleElement);
27
- }
24
+ removeStyle("data-ui5-theme-properties", BASE_THEME_PACKAGE);
28
25
  };
29
26
 
30
27
  const loadComponentPackages = async theme => {
@@ -35,7 +32,7 @@ const loadComponentPackages = async theme => {
35
32
  }
36
33
 
37
34
  const cssText = await getThemeProperties(packageName, theme);
38
- createThemePropertiesStyleTag(cssText, packageName);
35
+ createOrUpdateStyle(cssText, "data-ui5-theme-properties", packageName);
39
36
  });
40
37
  };
41
38
 
@@ -0,0 +1,20 @@
1
+ import { getUrl } from "../CSP.js";
2
+
3
+ const flatten = arr => {
4
+ return arr.reduce((acc, val) => acc.concat(Array.isArray(val) ? flatten(val) : val), []);
5
+ };
6
+
7
+ const getEffectiveLinksHrefs = (ElementClass, forStaticArea = false) => {
8
+ let stylesData = ElementClass[forStaticArea ? "staticAreaStyles" : "styles"];
9
+ if (!stylesData) {
10
+ return;
11
+ }
12
+
13
+ if (!Array.isArray(stylesData)) {
14
+ stylesData = [stylesData];
15
+ }
16
+
17
+ return flatten(stylesData).filter(data => !!data).map(data => getUrl(data.packageName, data.fileName));
18
+ };
19
+
20
+ export default getEffectiveLinksHrefs;
@@ -1,9 +1,11 @@
1
1
  const getStylesString = styles => {
2
2
  if (Array.isArray(styles)) {
3
- return flatten(styles.filter(style => !!style)).join(" ");
3
+ return flatten(styles.filter(style => !!style)).map(style => {
4
+ return typeof style === "string" ? style : style.content;
5
+ }).join(" ");
4
6
  }
5
7
 
6
- return styles;
8
+ return typeof styles === "string" ? styles : styles.content;
7
9
  };
8
10
 
9
11
  const flatten = arr => {
@@ -0,0 +1,23 @@
1
+ import getEffectiveLinksHrefs from "./getEffectiveLinksHrefs.js";
2
+ import createLinkInHead from "../util/createLinkInHead.js";
3
+ import { shouldUseLinks, shouldPreloadLinks } from "../CSP.js";
4
+
5
+ const preloaded = new Set();
6
+
7
+ const preloadLinks = ElementClass => {
8
+ if (!shouldUseLinks() || !shouldPreloadLinks()) {
9
+ return;
10
+ }
11
+
12
+ const linksHrefs = getEffectiveLinksHrefs(ElementClass, false) || [];
13
+ const staticAreaLinksHrefs = getEffectiveLinksHrefs(ElementClass, true) || [];
14
+
15
+ [...linksHrefs, ...staticAreaLinksHrefs].forEach(href => {
16
+ if (!preloaded.has(href)) {
17
+ createLinkInHead(href, { rel: "preload", as: "style" });
18
+ preloaded.add(href);
19
+ }
20
+ });
21
+ };
22
+
23
+ export default preloadLinks;
@@ -1,7 +1,9 @@
1
1
  import executeTemplate from "./renderer/executeTemplate.js";
2
2
  import getConstructableStyle from "./theming/getConstructableStyle.js";
3
3
  import getEffectiveStyle from "./theming/getEffectiveStyle.js";
4
+ import getEffectiveLinksHrefs from "./theming/getEffectiveLinksHrefs.js";
4
5
  import isLegacyBrowser from "./isLegacyBrowser.js";
6
+ import { shouldUseLinks } from "./CSP.js";
5
7
 
6
8
  /**
7
9
  * Updates the shadow root of a UI5Element or its static area item
@@ -9,18 +11,20 @@ import isLegacyBrowser from "./isLegacyBrowser.js";
9
11
  * @param forStaticArea
10
12
  */
11
13
  const updateShadowRoot = (element, forStaticArea = false) => {
12
- let styleToPrepend;
14
+ let styleStrOrHrefsArr;
13
15
  const template = forStaticArea ? "staticAreaTemplate" : "template";
14
16
  const shadowRoot = forStaticArea ? element.staticAreaItem.shadowRoot : element.shadowRoot;
15
17
  const renderResult = executeTemplate(element.constructor[template], element);
16
18
 
17
- if (document.adoptedStyleSheets) { // Chrome
19
+ if (shouldUseLinks()) {
20
+ styleStrOrHrefsArr = getEffectiveLinksHrefs(element.constructor, forStaticArea);
21
+ } else if (document.adoptedStyleSheets) { // Chrome
18
22
  shadowRoot.adoptedStyleSheets = getConstructableStyle(element.constructor, forStaticArea);
19
23
  } else if (!isLegacyBrowser()) { // FF, Safari
20
- styleToPrepend = getEffectiveStyle(element.constructor, forStaticArea);
24
+ styleStrOrHrefsArr = getEffectiveStyle(element.constructor, forStaticArea);
21
25
  }
22
26
 
23
- element.constructor.render(renderResult, shadowRoot, styleToPrepend, { host: element });
27
+ element.constructor.render(renderResult, shadowRoot, styleStrOrHrefsArr, { host: element });
24
28
  };
25
29
 
26
30
  export default updateShadowRoot;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Creates a <link> tag in the <head> tag
3
+ * @param href - the CSS
4
+ * @param attributes - optional attributes to add to the tag
5
+ * @returns {HTMLElement}
6
+ */
7
+ const createLinkInHead = (href, attributes = {}) => {
8
+ const link = document.createElement("link");
9
+ link.type = "text/css";
10
+ link.rel = "stylesheet";
11
+
12
+ Object.entries(attributes).forEach(pair => link.setAttribute(...pair));
13
+
14
+ link.href = href;
15
+ document.head.appendChild(link);
16
+ return link;
17
+ };
18
+
19
+ export default createLinkInHead;
package/hash.txt CHANGED
@@ -1 +1 @@
1
- JNWgflBAJXdY6hVcYESgptjZSY4=
1
+ u7lf+BYiNgLsA+5UYY5y8xTW0Po=
@@ -0,0 +1,18 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const mkdirp = require('mkdirp');
4
+ const CleanCSS = require('clean-css');
5
+
6
+ mkdirp.sync("dist/generated/css/");
7
+ fs.readdirSync("src/css/").filter(file => file.endsWith(".css")).forEach(file => {
8
+ let content = fs.readFileSync(path.join("src/css/", file));
9
+ const res = new CleanCSS().minify(`${content}`);
10
+ content = `export default {
11
+ packageName: "@ui5/webcomponents-base",
12
+ fileName: "${file}",
13
+ content: \`${res.styles}\`
14
+ };`;
15
+
16
+ fs.writeFileSync(path.join("dist/generated/css/", `${file}.js`), content);
17
+ });
18
+
@@ -1,6 +1,7 @@
1
1
  const resolve = require("resolve");
2
2
 
3
3
  const assetParametersScript = resolve.sync("@ui5/webcomponents-base/lib/generate-asset-parameters/index.js");
4
+ const stylesScript = resolve.sync("@ui5/webcomponents-base/lib/generate-styles/index.js");
4
5
  const serve = resolve.sync("@ui5/webcomponents-tools/lib/serve/index.js");
5
6
  const generateHash = resolve.sync("@ui5/webcomponents-tools/lib/hash/generate.js");
6
7
  const hashIsUpToDate = resolve.sync("@ui5/webcomponents-tools/lib/hash/upToDate.js");
@@ -12,7 +13,7 @@ const UP_TO_DATE = `node "${hashIsUpToDate}" dist/ hash.txt && echo "Up to date.
12
13
  const scripts = {
13
14
  clean: "rimraf dist && rimraf .port",
14
15
  lint: "eslint . --config config/.eslintrc.js",
15
- prepare: "nps clean integrate copy generateAssetParameters",
16
+ prepare: "nps clean integrate copy generateAssetParameters generateStyles",
16
17
  integrate: {
17
18
  default: "nps integrate.copy-used-modules integrate.copy-overlay integrate.replace-amd integrate.replace-export-true integrate.replace-export-false integrate.amd-to-es6 integrate.replace-global-core-usage integrate.esm-abs-to-rel integrate.third-party",
18
19
  "copy-used-modules": `node "${copyUsedModules}" ./used-modules.txt dist/`,
@@ -35,15 +36,17 @@ const scripts = {
35
36
  },
36
37
  copy: {
37
38
  default: "nps copy.src copy.test",
38
- src: `copy-and-watch "src/**/*.js" dist/`,
39
+ src: `copy-and-watch "src/**/*.{js,css}" dist/`,
39
40
  test: `copy-and-watch "test/**/*.*" dist/test-resources`,
40
41
  },
41
42
  generateAssetParameters: `node "${assetParametersScript}"`,
43
+ generateStyles: `node "${stylesScript}"`,
42
44
  watch: {
43
- default: 'concurrently "nps watch.test" "nps watch.src" "nps watch.bundle"',
45
+ default: 'concurrently "nps watch.test" "nps watch.src" "nps watch.bundle" "nps watch.styles"',
44
46
  src: 'nps "copy.src --watch --skip-initial-copy"',
45
47
  test: 'nps "copy.test --watch --skip-initial-copy"',
46
48
  bundle: "rollup --config config/rollup.config.js -w --environment DEV",
49
+ styles: 'chokidar "src/css/*.css" -c "nps generateStyles"'
47
50
  },
48
51
  dev: 'concurrently "nps serve" "nps watch"',
49
52
  start: "nps prepare dev",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ui5/webcomponents-base",
3
- "version": "0.0.0-db2be6526",
3
+ "version": "0.0.0-dc3ccac50",
4
4
  "description": "UI5 Web Components: webcomponents.base",
5
5
  "author": "SAP SE (https://www.sap.com)",
6
6
  "license": "Apache-2.0",
@@ -37,8 +37,9 @@
37
37
  "devDependencies": {
38
38
  "@buxlabs/amd-to-es6": "0.16.1",
39
39
  "@openui5/sap.ui.core": "1.94.0",
40
- "@ui5/webcomponents-tools": "0.0.0-db2be6526",
41
- "chromedriver": "94.0.0",
40
+ "@ui5/webcomponents-tools": "0.0.0-dc3ccac50",
41
+ "chromedriver": "95.0.0",
42
+ "clean-css": "^5.2.2",
42
43
  "copy-and-watch": "^0.1.5",
43
44
  "eslint": "^7.22.0",
44
45
  "mkdirp": "^1.0.4",
package/src/CSP.js ADDED
@@ -0,0 +1,59 @@
1
+ const roots = new Map();
2
+ let useLinks = false;
3
+ let preloadLinks = true;
4
+
5
+ /**
6
+ * Use this function to provide the path to the directory where the css resources for the given package will be served from
7
+ *
8
+ * @public
9
+ * @param packageName name of the package that is being configured
10
+ * @param root path, accessible by the server that will serve the css resources
11
+ */
12
+ const setPackageCSSRoot = (packageName, root) => {
13
+ roots.set(packageName, root);
14
+ };
15
+
16
+ const getUrl = (packageName, path) => {
17
+ return `${roots.get(packageName)}${path}`;
18
+ };
19
+
20
+ /**
21
+ * Call this function to enable or disable the usage of <link> tags instead of <style> tags to achieve CSP compliance
22
+ * Example: "setUseLinks(true)" will unconditionally use <link> tags for all browsers;
23
+ * Example: "setUseLinks(!document.adoptedStyleSheets) will only enable the usage of <link> tags for browsers that do not support constructable stylesheets.
24
+ *
25
+ * @public
26
+ * @param use whether links will be used
27
+ */
28
+ const setUseLinks = use => {
29
+ useLinks = use;
30
+ };
31
+
32
+ /**
33
+ * Call this function to enable or disable the preloading of <link> tags.
34
+ * Note: only taken into account when <link> tags are being used.
35
+ * Note: links are being preloaded by default, so call "setPreloadLinks(false)" to opt out of this.
36
+ *
37
+ * @public
38
+ * @param preload
39
+ */
40
+ const setPreloadLinks = preload => {
41
+ preloadLinks = preload;
42
+ };
43
+
44
+ const shouldUseLinks = () => {
45
+ return useLinks;
46
+ };
47
+
48
+ const shouldPreloadLinks = () => {
49
+ return preloadLinks;
50
+ };
51
+
52
+ export {
53
+ setPackageCSSRoot,
54
+ getUrl,
55
+ setUseLinks,
56
+ setPreloadLinks,
57
+ shouldUseLinks,
58
+ shouldPreloadLinks,
59
+ };
package/src/FontFace.js CHANGED
@@ -1,107 +1,7 @@
1
- /**
2
- * CSS font face used for the texts provided by SAP.
3
- */
4
1
  import { hasStyle, createStyle } from "./ManagedStyles.js";
5
2
  import { getFeature } from "./FeaturesRegistry.js";
6
-
7
- /* CDN Locations */
8
- const font72RegularWoff = `https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Regular.woff?ui5-webcomponents`;
9
- const font72RegularWoff2 = `https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Regular.woff2?ui5-webcomponents`;
10
-
11
- const font72RegularFullWoff = `https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Regular-full.woff?ui5-webcomponents`;
12
- const font72RegularFullWoff2 = `https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Regular-full.woff2?ui5-webcomponents`;
13
-
14
- const font72BoldWoff = `https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Bold.woff?ui5-webcomponents`;
15
- const font72BoldWoff2 = `https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Bold.woff2?ui5-webcomponents`;
16
-
17
- const font72BoldFullWoff = `https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Bold-full.woff?ui5-webcomponents`;
18
- const font72BoldFullWoff2 = `https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Bold-full.woff2?ui5-webcomponents`;
19
-
20
- const font72BlackWoff = `https://openui5nightly.hana.ondemand.com/resources/sap/ui/core/themes/sap_horizon/fonts/72-Black.woff?ui5-webcomponents`;
21
- const font72BlackWoff2 = `https://openui5nightly.hana.ondemand.com/resources/sap/ui/core/themes/sap_horizon/fonts/72-Black.woff2?ui5-webcomponents`;
22
-
23
- const fontFaceCSS = `
24
- @font-face {
25
- font-family: "72";
26
- font-style: normal;
27
- font-weight: 400;
28
- src: local("72"),
29
- url(${font72RegularWoff2}) format("woff2"),
30
- url(${font72RegularWoff}) format("woff");
31
- }
32
-
33
- @font-face {
34
- font-family: "72full";
35
- font-style: normal;
36
- font-weight: 400;
37
- src: local('72-full'),
38
- url(${font72RegularFullWoff2}) format("woff2"),
39
- url(${font72RegularFullWoff}) format("woff");
40
-
41
- }
42
-
43
- @font-face {
44
- font-family: "72";
45
- font-style: normal;
46
- font-weight: 700;
47
- src: local('72-Bold'),
48
- url(${font72BoldWoff2}) format("woff2"),
49
- url(${font72BoldWoff}) format("woff");
50
- }
51
-
52
- @font-face {
53
- font-family: "72full";
54
- font-style: normal;
55
- font-weight: 700;
56
- src: local('72-Bold-full'),
57
- url(${font72BoldFullWoff2}) format("woff2"),
58
- url(${font72BoldFullWoff}) format("woff");
59
- }
60
-
61
- @font-face {
62
- font-family: "72Black";
63
- font-style: bold;
64
- font-weight: 900;
65
- src: local('72Black'),
66
- url(${font72BlackWoff2}) format("woff2"),
67
- url(${font72BlackWoff}) format("woff");
68
- }
69
- `;
70
-
71
- /**
72
- * Some diacritics are supported by the 72 font:
73
- * * Grave
74
- * * Acute
75
- * * Circumflex
76
- * * Tilde
77
- *
78
- * However, the following diacritics and the combination of multiple diacritics (including the supported ones) are not supported:
79
- * * Breve
80
- * * Horn
81
- * * Dot below
82
- * * Hook above
83
- *
84
- *
85
- * Override for the characters that aren't covered by the '72' font to other system fonts
86
- *
87
- * U+0102-0103: A and a with Breve
88
- * U+01A0-01A1: O and o with Horn
89
- * U+01AF-01B0: U and u with Horn
90
- * U+1EA0-1EB7: A and a with diacritics that are not supported by the font and combination of multiple diacritics
91
- * U+1EB8-1EC7: E and e with diacritics that are not supported by the font and combination of multiple diacritics
92
- * U+1EC8-1ECB: I and i with diacritics that are not supported by the font and combination of multiple diacritics
93
- * U+1ECC-1EE3: O and o with diacritics that are not supported by the font and combination of multiple diacritics
94
- * U+1EE4-1EF1: U and u with diacritics that are not supported by the font and combination of multiple diacritics
95
- * U+1EF4-1EF7: Y and y with diacritics that are not supported by the font and combination of multiple diacritics
96
- *
97
- */
98
- const overrideFontFaceCSS = `
99
- @font-face {
100
- font-family: '72override';
101
- unicode-range: U+0102-0103, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EB7, U+1EB8-1EC7, U+1EC8-1ECB, U+1ECC-1EE3, U+1EE4-1EF1, U+1EF4-1EF7;
102
- src: local('Arial'), local('Helvetica'), local('sans-serif');
103
- }
104
- `;
3
+ import fontFaceCSS from "./generated/css/FontFace.css.js";
4
+ import overrideFontFaceCSS from "./generated/css/OverrideFontFace.css.js";
105
5
 
106
6
  const insertFontFace = () => {
107
7
  const OpenUI5Support = getFeature("OpenUI5Support");
@@ -1,11 +1,20 @@
1
1
  import createStyleInHead from "./util/createStyleInHead.js";
2
+ import createLinkInHead from "./util/createLinkInHead.js";
3
+ import { shouldUseLinks, getUrl } from "./CSP.js";
2
4
 
3
5
  const getStyleId = (name, value) => {
4
6
  return value ? `${name}|${value}` : name;
5
7
  };
6
8
 
7
- const createStyle = (content, name, value = "") => {
8
- if (document.adoptedStyleSheets) {
9
+ const createStyle = (data, name, value = "") => {
10
+ const content = typeof data === "string" ? data : data.content;
11
+
12
+ if (shouldUseLinks()) {
13
+ const attributes = {};
14
+ attributes[name] = value;
15
+ const href = getUrl(data.packageName, data.fileName);
16
+ createLinkInHead(href, attributes);
17
+ } else if (document.adoptedStyleSheets) {
9
18
  const stylesheet = new CSSStyleSheet();
10
19
  stylesheet.replaceSync(content);
11
20
  stylesheet._ui5StyleId = getStyleId(name, value); // set an id so that we can find the style later
@@ -17,8 +26,12 @@ const createStyle = (content, name, value = "") => {
17
26
  }
18
27
  };
19
28
 
20
- const updateStyle = (content, name, value = "") => {
21
- if (document.adoptedStyleSheets) {
29
+ const updateStyle = (data, name, value = "") => {
30
+ const content = typeof data === "string" ? data : data.content;
31
+
32
+ if (shouldUseLinks()) {
33
+ document.querySelector(`head>link[${name}="${value}"]`).href = getUrl(data.packageName, data.fileName);
34
+ } else if (document.adoptedStyleSheets) {
22
35
  document.adoptedStyleSheets.find(sh => sh._ui5StyleId === getStyleId(name, value)).replaceSync(content || "");
23
36
  } else {
24
37
  document.querySelector(`head>style[${name}="${value}"]`).textContent = content || "";
@@ -26,6 +39,10 @@ const updateStyle = (content, name, value = "") => {
26
39
  };
27
40
 
28
41
  const hasStyle = (name, value = "") => {
42
+ if (shouldUseLinks()) {
43
+ return !!document.querySelector(`head>link[${name}="${value}"]`);
44
+ }
45
+
29
46
  if (document.adoptedStyleSheets) {
30
47
  return !!document.adoptedStyleSheets.find(sh => sh._ui5StyleId === getStyleId(name, value));
31
48
  }
@@ -33,4 +50,34 @@ const hasStyle = (name, value = "") => {
33
50
  return !!document.querySelector(`head>style[${name}="${value}"]`);
34
51
  };
35
52
 
36
- export { createStyle, hasStyle, updateStyle };
53
+ const removeStyle = (name, value = "") => {
54
+ if (shouldUseLinks()) {
55
+ const linkElement = document.querySelector(`head>link[${name}="${value}"]`);
56
+ if (linkElement) {
57
+ linkElement.parentElement.removeChild(linkElement);
58
+ }
59
+ } else if (document.adoptedStyleSheets) {
60
+ document.adoptedStyleSheets = document.adoptedStyleSheets.filter(sh => sh._ui5StyleId !== getStyleId(name, value));
61
+ } else {
62
+ const styleElement = document.querySelector(`head > style[${name}="${value}"]`);
63
+ if (styleElement) {
64
+ styleElement.parentElement.removeChild(styleElement);
65
+ }
66
+ }
67
+ };
68
+
69
+ const createOrUpdateStyle = (data, name, value = "") => {
70
+ if (hasStyle(name, value)) {
71
+ updateStyle(data, name, value);
72
+ } else {
73
+ createStyle(data, name, value);
74
+ }
75
+ };
76
+
77
+ export {
78
+ createStyle,
79
+ hasStyle,
80
+ updateStyle,
81
+ removeStyle,
82
+ createOrUpdateStyle,
83
+ };
package/src/Render.js CHANGED
@@ -135,6 +135,7 @@ const _resolveTaskPromise = () => {
135
135
  * reRenderAllUI5Elements({tag: "ui5-button"}) -> re-renders only instances of ui5-button
136
136
  * reRenderAllUI5Elements({rtlAware: true}) -> re-renders only rtlAware components
137
137
  * reRenderAllUI5Elements({languageAware: true}) -> re-renders only languageAware components
138
+ * reRenderAllUI5Elements({themeAware: true}) -> re-renders only themeAware components
138
139
  * reRenderAllUI5Elements({rtlAware: true, languageAware: true}) -> re-renders components that are rtlAware or languageAware
139
140
  * etc...
140
141
  *
@@ -147,7 +148,8 @@ const reRenderAllUI5Elements = async filters => {
147
148
  const tag = element.constructor.getMetadata().getTag();
148
149
  const rtlAware = isRtlAware(element.constructor);
149
150
  const languageAware = element.constructor.getMetadata().isLanguageAware();
150
- if (!filters || (filters.tag === tag) || (filters.rtlAware && rtlAware) || (filters.languageAware && languageAware)) {
151
+ const themeAware = element.constructor.getMetadata().isThemeAware();
152
+ if (!filters || (filters.tag === tag) || (filters.rtlAware && rtlAware) || (filters.languageAware && languageAware) || (filters.themeAware && themeAware)) {
151
153
  renderDeferred(element);
152
154
  }
153
155
  });
@@ -76,15 +76,6 @@ class StaticAreaItem extends HTMLElement {
76
76
  return this.shadowRoot;
77
77
  }
78
78
 
79
- /**
80
- * @protected
81
- * @param refName
82
- * @returns {Element}
83
- */
84
- getStableDomRef(refName) {
85
- return this.shadowRoot.querySelector(`[data-ui5-stable=${refName}]`);
86
- }
87
-
88
79
  static getTag() {
89
80
  const pureTag = "ui5-static-area-item";
90
81
  const suffix = getEffectiveScopingSuffixForTag(pureTag);
@@ -1,24 +1,5 @@
1
1
  import { hasStyle, createStyle } from "./ManagedStyles.js";
2
-
3
- const systemCSSVars = `
4
- :root {
5
- --_ui5_content_density:cozy;
6
- }
7
-
8
- [data-ui5-compact-size],
9
- .ui5-content-density-compact,
10
- .sapUiSizeCompact {
11
- --_ui5_content_density:compact;
12
- }
13
-
14
- [dir="rtl"] {
15
- --_ui5_dir:rtl;
16
- }
17
-
18
- [dir="ltr"] {
19
- --_ui5_dir:ltr;
20
- }
21
- `;
2
+ import systemCSSVars from "./generated/css/SystemCSSVars.css.js";
22
3
 
23
4
  const insertSystemCSSVars = () => {
24
5
  if (!hasStyle("data-ui5-system-css-vars")) {
package/src/UI5Element.js CHANGED
@@ -18,7 +18,7 @@ import { isSlot, getSlotName, getSlottedElementsList } from "./util/SlotsHelper.
18
18
  import arraysAreEqual from "./util/arraysAreEqual.js";
19
19
  import getClassCopy from "./util/getClassCopy.js";
20
20
  import { markAsRtlAware } from "./locale/RTLAwareRegistry.js";
21
- import isLegacyBrowser from "./isLegacyBrowser.js";
21
+ import preloadLinks from "./theming/preloadLinks.js";
22
22
 
23
23
  let autoId = 0;
24
24
 
@@ -607,25 +607,27 @@ class UI5Element extends HTMLElement {
607
607
 
608
608
  /**
609
609
  * Returns the DOM Element inside the Shadow Root that corresponds to the opening tag in the UI5 Web Component's template
610
+ * *Note:* For logical (abstract) elements (items, options, etc...), returns the part of the parent's DOM that represents this option
610
611
  * Use this method instead of "this.shadowRoot" to read the Shadow DOM, if ever necessary
612
+ *
611
613
  * @public
612
614
  */
613
615
  getDomRef() {
616
+ // If a component set _getRealDomRef to its children, use the return value of this function
617
+ if (typeof this._getRealDomRef === "function") {
618
+ return this._getRealDomRef();
619
+ }
620
+
614
621
  if (!this.shadowRoot || this.shadowRoot.children.length === 0) {
615
622
  return;
616
623
  }
617
624
 
618
- this._assertShadowRootStructure();
619
-
620
- return this.shadowRoot.children.length === 1
621
- ? this.shadowRoot.children[0] : this.shadowRoot.children[1];
622
- }
623
-
624
- _assertShadowRootStructure() {
625
- const expectedChildrenCount = document.adoptedStyleSheets || isLegacyBrowser() ? 1 : 2;
626
- if (this.shadowRoot.children.length !== expectedChildrenCount) {
625
+ const children = [...this.shadowRoot.children].filter(child => !["link", "style"].includes(child.localName));
626
+ if (children.length !== 1) {
627
627
  console.warn(`The shadow DOM for ${this.constructor.getMetadata().getTag()} does not have a top level element, the getDomRef() method might not work as expected`); // eslint-disable-line
628
628
  }
629
+
630
+ return children[0];
629
631
  }
630
632
 
631
633
  /**
@@ -651,17 +653,6 @@ class UI5Element extends HTMLElement {
651
653
  return this.getFocusDomRef();
652
654
  }
653
655
 
654
- /**
655
- * Use this method in order to get a reference to an element in the shadow root of the web component or the static area item of the component
656
- * @public
657
- * @method
658
- * @param {String} refName Defines the name of the stable DOM ref
659
- */
660
- getStableDomRef(refName) {
661
- const staticAreaResult = this.staticAreaItem && this.staticAreaItem.getStableDomRef(refName);
662
- return staticAreaResult || this.getDomRef().querySelector(`[data-ui5-stable=${refName}]`);
663
- }
664
-
665
656
  /**
666
657
  * Set the focus to the element, returned by "getFocusDomRef()" (marked by "data-sap-focus-ref")
667
658
  * @public
@@ -988,6 +979,7 @@ class UI5Element extends HTMLElement {
988
979
  this._generateAccessors();
989
980
  registerTag(tag);
990
981
  window.customElements.define(tag, this);
982
+ preloadLinks(this);
991
983
 
992
984
  if (altTag && !customElements.get(altTag)) {
993
985
  registerTag(altTag);
@@ -212,6 +212,14 @@ class UI5ElementMetadata {
212
212
  return !!this.metadata.languageAware;
213
213
  }
214
214
 
215
+ /**
216
+ * Determines whether this UI5 Element has any theme dependant carachteristics.
217
+ * @returns {boolean}
218
+ */
219
+ isThemeAware() {
220
+ return !!this.metadata.themeAware;
221
+ }
222
+
215
223
  /**
216
224
  * Matches a changed entity (property/slot) with the given name against the "invalidateOnChildChange" configuration
217
225
  * and determines whether this should cause and invalidation