@ui5/webcomponents-base 1.8.0 → 1.9.1

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 (50) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/bundle.esm.js +1 -0
  3. package/dist/InitialConfiguration.js +23 -3
  4. package/dist/StaticAreaItem.js +7 -1
  5. package/dist/api.json +1 -0
  6. package/dist/asset-registries/Illustrations.js +30 -1
  7. package/dist/assets/bundle.esm.f4192314.js +55 -0
  8. package/dist/config/ThemeRoots.js +39 -0
  9. package/dist/features/F6Navigation.js +22 -25
  10. package/dist/features/OpenUI5Support.js +1 -0
  11. package/dist/generated/VersionInfo.js +4 -4
  12. package/dist/generated/templates/elements/WithComplexTemplateTemplate.lit.js +11 -0
  13. package/dist/theming/applyTheme.js +7 -2
  14. package/dist/types/CSSColor.js +11 -0
  15. package/dist/types/CSSSize.js +11 -0
  16. package/dist/types/CalendarType.js +37 -0
  17. package/dist/types/DOMReference.js +4 -0
  18. package/dist/types/DataType.js +6 -0
  19. package/dist/types/Float.js +11 -0
  20. package/dist/types/Integer.js +11 -0
  21. package/dist/types/InvisibleMessageMode.js +17 -1
  22. package/dist/types/PopupState.js +20 -0
  23. package/dist/types/ValueState.js +43 -1
  24. package/dist/util/AriaLabelHelper.js +17 -0
  25. package/dist/util/createLinkInHead.js +6 -1
  26. package/dist/validateThemeRoot.js +58 -0
  27. package/package-scripts.js +3 -1
  28. package/package.json +3 -3
  29. package/src/InitialConfiguration.js +23 -3
  30. package/src/StaticAreaItem.js +7 -1
  31. package/src/asset-registries/Illustrations.js +30 -1
  32. package/src/config/ThemeRoots.js +39 -0
  33. package/src/features/F6Navigation.js +22 -25
  34. package/src/features/OpenUI5Support.js +1 -0
  35. package/src/theming/applyTheme.js +7 -2
  36. package/src/types/CSSColor.js +11 -0
  37. package/src/types/CSSSize.js +11 -0
  38. package/src/types/CalendarType.js +37 -0
  39. package/src/types/DOMReference.js +4 -0
  40. package/src/types/DataType.js +6 -0
  41. package/src/types/Float.js +11 -0
  42. package/src/types/Integer.js +11 -0
  43. package/src/types/InvisibleMessageMode.js +17 -1
  44. package/src/types/PopupState.js +20 -0
  45. package/src/types/ValueState.js +43 -1
  46. package/src/util/AriaLabelHelper.js +17 -0
  47. package/src/util/createLinkInHead.js +6 -1
  48. package/src/validateThemeRoot.js +58 -0
  49. package/dist/assets/bundle.esm.62217b93.js +0 -43
  50. package/hash.txt +0 -1
@@ -3,6 +3,7 @@ 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";
6
+ import { attachCustomThemeStylesToHead, getThemeRoot } from "../config/ThemeRoots.js";
6
7
 
7
8
  const BASE_THEME_PACKAGE = "@ui5/webcomponents-theming";
8
9
 
@@ -40,7 +41,7 @@ const loadComponentPackages = async theme => {
40
41
  });
41
42
  };
42
43
 
43
- const detectExternalTheme = () => {
44
+ const detectExternalTheme = async theme => {
44
45
  // If theme designer theme is detected, use this
45
46
  const extTheme = getThemeDesignerTheme();
46
47
  if (extTheme) {
@@ -56,11 +57,15 @@ const detectExternalTheme = () => {
56
57
  themeName: OpenUI5Support.getConfigurationSettingsObject().theme, // just themeName, baseThemeName is only relevant for custom themes
57
58
  };
58
59
  }
60
+ } else if (getThemeRoot()) {
61
+ await attachCustomThemeStylesToHead(theme);
62
+
63
+ return getThemeDesignerTheme();
59
64
  }
60
65
  };
61
66
 
62
67
  const applyTheme = async theme => {
63
- const extTheme = detectExternalTheme();
68
+ const extTheme = await detectExternalTheme(theme);
64
69
 
65
70
  // Only load theme_base properties if there is no externally loaded theme, or there is, but it is not being loaded
66
71
  if (!extTheme || theme !== extTheme.themeName) {
@@ -1,5 +1,16 @@
1
1
  import DataType from "./DataType.js";
2
2
 
3
+ /**
4
+ * @class
5
+ * CSSColor data type.
6
+ *
7
+ * @extends sap.ui.webcomponents.base.types.DataType
8
+ * @constructor
9
+ * @author SAP SE
10
+ * @alias sap.ui.webcomponents.base.types.CSSColor
11
+ * @public
12
+ * @enum {string}
13
+ */
3
14
  class CSSColor extends DataType {
4
15
  static isValid(value) {
5
16
  return /^(#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})|rgb\(\s*((1?[0-9]?[0-9]|2([0-4][0-9]|5[0-5]))|([0-9]?[0-9](\.[0-9]+)?|100(\.0+)?)%)\s*(,\s*((1?[0-9]?[0-9]|2([0-4][0-9]|5[0-5]))|([0-9]?[0-9](\.[0-9]+)?|100(\.0+)?)%)\s*){2}\)|rgba\((\s*((1?[0-9]?[0-9]|2([0-4][0-9]|5[0-5]))|([0-9]?[0-9](\.[0-9]+)?|100(\.0+)?)%)\s*,){3}\s*(0(\.[0-9]+)?|1(\.0+)?)\s*\)|hsl\(\s*([0-2]?[0-9]?[0-9]|3([0-5][0-9]|60))\s*(,\s*(([0-9]?[0-9](\.[0-9]+)?|100(\.0+)?)%)\s*){2}\)|hsla\(\s*([0-2]?[0-9]?[0-9]|3([0-5][0-9]|60))\s*,(\s*(([0-9]?[0-9](\.[0-9]+)?|100(\.0+)?)%)\s*,){2}\s*(0(\.[0-9]+)?|1(\.0+)?)\s*\)|aliceblue|antiquewhite|aqua|aquamarine|azure|beige|bisque|black|blanchedalmond|blue|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|cyan|darkblue|darkcyan|darkgoldenrod|darkgray|darkgrey|darkgreen|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkslategrey|darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dimgrey|dodgerblue|firebrick|floralwhite|forestgreen|fuchsia|gainsboro|ghostwhite|gold|goldenrod|gray|grey|green|greenyellow|honeydew|hotpink|indianred|indigo|ivory|khaki|lavender|lavenderblush|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|lightgoldenrodyellow|lightgray|lightgrey|lightgreen|lightpink|lightsalmon|lightseagreen|lightskyblue|lightslategray|lightslategrey|lightsteelblue|lightyellow|lime|limegreen|linen|magenta|maroon|mediumaquamarine|mediumblue|mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|navajowhite|navy|oldlace|olive|olivedrab|orange|orangered|orchid|palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|peru|pink|plum|powderblue|purple|red|rosybrown|royalblue|saddlebrown|salmon|sandybrown|seagreen|seashell|sienna|silverskyblue|slateblue|slategray|slategrey|snow|springgreen|steelblue|tan|teal|thistle|tomato|turquoise|violet|wheat|white|whitesmoke|yellow|yellowgreen|transparent|inherit|)$/.test(value ); // eslint-disable-line
@@ -1,5 +1,16 @@
1
1
  import DataType from "./DataType.js";
2
2
 
3
+ /**
4
+ * @class
5
+ * CSSSize data type.
6
+ *
7
+ * @extends sap.ui.webcomponents.base.types.DataType
8
+ * @constructor
9
+ * @author SAP SE
10
+ * @alias sap.ui.webcomponents.base.types.CSSSize
11
+ * @public
12
+ * @enum {string}
13
+ */
3
14
  class CSSSize extends DataType {
4
15
  static isValid(value) {
5
16
  return /^(auto|inherit|[-+]?(0*|([0-9]+|[0-9]*\.[0-9]+)([rR][eE][mM]|[eE][mM]|[eE][xX]|[pP][xX]|[cC][mM]|[mM][mM]|[iI][nN]|[pP][tT]|[pP][cC]|%))|calc\(\s*(\(\s*)*[-+]?(([0-9]+|[0-9]*\.[0-9]+)([rR][eE][mM]|[eE][mM]|[eE][xX]|[pP][xX]|[cC][mM]|[mM][mM]|[iI][nN]|[pP][tT]|[pP][cC]|%)?)(\s*(\)\s*)*(\s[-+]\s|[*\/])\s*(\(\s*)*([-+]?(([0-9]+|[0-9]*\.[0-9]+)([rR][eE][mM]|[eE][mM]|[eE][xX]|[pP][xX]|[cC][mM]|[mM][mM]|[iI][nN]|[pP][tT]|[pP][cC]|%)?)))*\s*(\)\s*)*\))$/.test(value); // eslint-disable-line
@@ -2,15 +2,52 @@ import DataType from "./DataType.js";
2
2
 
3
3
  /**
4
4
  * Different calendar types.
5
+ * @lends sap.ui.webcomponents.base.types.CalendarType.prototype
6
+ * @public
5
7
  */
6
8
  const CalendarTypes = {
9
+ /**
10
+ * @public
11
+ * @type {Gregorian}
12
+ */
7
13
  Gregorian: "Gregorian",
14
+
15
+ /**
16
+ * @public
17
+ * @type {Islamic}
18
+ */
8
19
  Islamic: "Islamic",
20
+
21
+ /**
22
+ * @public
23
+ * @type {Japanese}
24
+ */
9
25
  Japanese: "Japanese",
26
+
27
+ /**
28
+ * @public
29
+ * @type {Buddhist}
30
+ */
10
31
  Buddhist: "Buddhist",
32
+
33
+ /**
34
+ * @public
35
+ * @type {Persian}
36
+ */
11
37
  Persian: "Persian",
12
38
  };
13
39
 
40
+ /**
41
+ * @class
42
+ * Different calendar types.
43
+ *
44
+ * @extends sap.ui.webcomponents.base.types.DataType
45
+ * @constructor
46
+ * @author SAP SE
47
+ * @alias sap.ui.webcomponents.base.types.CalendarType
48
+ * @public
49
+ * @enum {string}
50
+ */
14
51
  class CalendarType extends DataType {
15
52
  static isValid(value) {
16
53
  return !!CalendarTypes[value];
@@ -5,6 +5,10 @@ import DataType from "./DataType.js";
5
5
  * DOM Element reference or ID.
6
6
  * <b>Note:</b> If an ID is passed, it is expected to be part of the same <code>document</code> element as the consuming component.
7
7
  *
8
+ * @constructor
9
+ * @extends sap.ui.webcomponents.base.types.DataType
10
+ * @author SAP SE
11
+ * @alias sap.ui.webcomponents.base.types.DOMReference
8
12
  * @public
9
13
  */
10
14
  class DOMReference extends DataType {
@@ -8,6 +8,12 @@
8
8
  * @public
9
9
  */
10
10
  class DataType {
11
+ /**
12
+ * Checks if the value is valid for its data type.
13
+ * @public
14
+ * @abstract
15
+ * @returns {Boolean}
16
+ */
11
17
  static isValid(value) {
12
18
  }
13
19
 
@@ -1,5 +1,16 @@
1
1
  import DataType from "./DataType.js";
2
2
 
3
+ /**
4
+ * @class
5
+ * Float data type.
6
+ *
7
+ * @constructor
8
+ * @extends sap.ui.webcomponents.base.types.DataType
9
+ * @author SAP SE
10
+ * @alias sap.ui.webcomponents.base.types.Float
11
+ * @public
12
+ * @enum {number}
13
+ */
3
14
  class Float extends DataType {
4
15
  static isValid(value) {
5
16
  // Assuming that integers are floats as well!
@@ -1,5 +1,16 @@
1
1
  import DataType from "./DataType.js";
2
2
 
3
+ /**
4
+ * @class
5
+ * Integer data type.
6
+ *
7
+ * @constructor
8
+ * @extends sap.ui.webcomponents.base.types.DataType
9
+ * @author SAP SE
10
+ * @alias sap.ui.webcomponents.base.types.Integer
11
+ * @public
12
+ * @enum {number}
13
+ */
3
14
  class Integer extends DataType {
4
15
  static isValid(value) {
5
16
  return Number.isInteger(value);
@@ -2,23 +2,39 @@ import DataType from "./DataType.js";
2
2
 
3
3
  /**
4
4
  * Enumeration for different mode behaviors of the <code>InvisibleMessage</code>.
5
- * @private
5
+ * @lends sap.ui.webcomponents.base.types.InvisibleMessageMode.prototype
6
+ * @public
6
7
  */
7
8
  const InvisibleMessageModes = {
8
9
 
9
10
  /**
10
11
  * Indicates that updates to the region should be presented at the next graceful opportunity,
11
12
  * such as at the end of reading the current sentence, or when the user pauses typing.
13
+ * @public
14
+ * @type {Polite}
12
15
  */
13
16
  Polite: "Polite",
14
17
 
15
18
  /**
16
19
  * Indicates that updates to the region have the highest priority and should be presented to the user immediately.
20
+ * @public
21
+ * @type {Assertive}
17
22
  */
18
23
  Assertive: "Assertive",
19
24
 
20
25
  };
21
26
 
27
+ /**
28
+ * @class
29
+ * Different types of InvisibleMessageMode.
30
+ *
31
+ * @extends sap.ui.webcomponents.base.types.DataType
32
+ * @constructor
33
+ * @author SAP SE
34
+ * @alias sap.ui.webcomponents.base.types.InvisibleMessageMode
35
+ * @public
36
+ * @enum {string}
37
+ */
22
38
  class InvisibleMessageMode extends DataType {
23
39
  static isValid(value) {
24
40
  return !!InvisibleMessageModes[value];
@@ -1,31 +1,51 @@
1
1
  import DataType from "./DataType.js";
2
2
 
3
+ /**
4
+ * Different types of PopupStates.
5
+ * @lends sap.ui.webcomponents.base.types.PopupState.prototype
6
+ * @public
7
+ */
3
8
  const PopupStates = {
4
9
  /**
5
10
  * Open and currently not changing states.
6
11
  * @public
12
+ * @type {OPEN}
7
13
  */
8
14
  OPEN: "OPEN",
9
15
 
10
16
  /**
11
17
  * Closed and currently not changing states.
12
18
  * @public
19
+ * @type {CLOSED}
13
20
  */
14
21
  CLOSED: "CLOSED",
15
22
 
16
23
  /**
17
24
  * Already left the CLOSED state, is not OPEN yet, but in the process of getting OPEN.
18
25
  * @public
26
+ * @type {OPENING}
19
27
  */
20
28
  OPENING: "OPENING",
21
29
 
22
30
  /**
23
31
  * Still open, but in the process of going to the CLOSED state.
24
32
  * @public
33
+ * @type {CLOSING}
25
34
  */
26
35
  CLOSING: "CLOSING",
27
36
  };
28
37
 
38
+ /**
39
+ * @class
40
+ * Different types of PopupState.
41
+ *
42
+ * @extends sap.ui.webcomponents.base.types.DataType
43
+ * @constructor
44
+ * @author SAP SE
45
+ * @alias sap.ui.webcomponents.base.types.PopupState
46
+ * @public
47
+ * @enum {string}
48
+ */
29
49
  class PopupState extends DataType {
30
50
  static isValid(value) {
31
51
  return !!PopupStates[value];
@@ -1,16 +1,58 @@
1
1
  import DataType from "./DataType.js";
2
2
 
3
3
  /**
4
- * Different states.
4
+ * Different types of ValueStates.
5
+ * @lends sap.ui.webcomponents.base.types.ValueState.prototype
6
+ * @public
5
7
  */
6
8
  const ValueStates = {
9
+ /**
10
+ *
11
+ * @public
12
+ * @type {None}
13
+ */
7
14
  None: "None",
15
+
16
+ /**
17
+ *
18
+ * @public
19
+ * @type {Success}
20
+ */
8
21
  Success: "Success",
22
+
23
+ /**
24
+ *
25
+ * @public
26
+ * @type {Warning}
27
+ */
9
28
  Warning: "Warning",
29
+
30
+ /**
31
+ *
32
+ * @public
33
+ * @type {Error}
34
+ */
10
35
  Error: "Error",
36
+
37
+ /**
38
+ *
39
+ * @public
40
+ * @type {Information}
41
+ */
11
42
  Information: "Information",
12
43
  };
13
44
 
45
+ /**
46
+ * @class
47
+ * Different types of ValueState.
48
+ *
49
+ * @extends sap.ui.webcomponents.base.types.DataType
50
+ * @constructor
51
+ * @author SAP SE
52
+ * @alias sap.ui.webcomponents.base.types.ValueState
53
+ * @public
54
+ * @enum {string}
55
+ */
14
56
  class ValueState extends DataType {
15
57
  static isValid(value) {
16
58
  return !!ValueStates[value];
@@ -33,7 +33,24 @@ const getAriaLabelledByTexts = (el, ownerDocument, readyIds = "") => {
33
33
  return result;
34
34
  };
35
35
 
36
+ /**
37
+ * @param {HTMLElement} el Defines the HTMLElement, for which you need to get all related "label for" texts
38
+ */
39
+ const getAssociatedLabelForTexts = el => {
40
+ const results = [];
41
+ const labels = el.getRootNode().querySelectorAll(`[ui5-label][for="${el.id}"],label[for="${el.id}"]`);
42
+
43
+ labels.forEach(label => results.push(label.textContent));
44
+
45
+ if (results.length) {
46
+ return results.join(" ");
47
+ }
48
+
49
+ return undefined;
50
+ };
51
+
36
52
  export {
37
53
  getEffectiveAriaLabelText,
38
54
  getAriaLabelledByTexts,
55
+ getAssociatedLabelForTexts,
39
56
  };
@@ -12,8 +12,13 @@ const createLinkInHead = (href, attributes = {}) => {
12
12
  Object.entries(attributes).forEach(pair => link.setAttribute(...pair));
13
13
 
14
14
  link.href = href;
15
+
15
16
  document.head.appendChild(link);
16
- return link;
17
+
18
+ return new Promise(resolve => {
19
+ link.addEventListener("load", resolve);
20
+ link.addEventListener("error", resolve);
21
+ });
17
22
  };
18
23
 
19
24
  export default createLinkInHead;
@@ -0,0 +1,58 @@
1
+ const getMetaTagValue = metaTagName => {
2
+ const metaTag = document.querySelector(`META[name="${metaTagName}"]`),
3
+ metaTagContent = metaTag && metaTag.getAttribute("content");
4
+
5
+ return metaTagContent;
6
+ };
7
+
8
+ const validateThemeOrigin = origin => {
9
+ const allowedOrigins = getMetaTagValue("sap-allowedThemeOrigins");
10
+
11
+ return allowedOrigins && allowedOrigins.split(",").some(allowedOrigin => {
12
+ return allowedOrigin === "*" || origin === allowedOrigin.trim();
13
+ });
14
+ };
15
+
16
+ const buildCorrectUrl = (oldUrl, newOrigin) => {
17
+ const oldUrlPath = new URL(oldUrl).pathname;
18
+
19
+ return new URL(oldUrlPath, newOrigin).toString();
20
+ };
21
+
22
+ const validateThemeRoot = themeRoot => {
23
+ let themeRootURL,
24
+ resultUrl;
25
+
26
+ try {
27
+ themeRootURL = new URL(themeRoot);
28
+
29
+ const origin = themeRootURL.origin;
30
+
31
+ themeRootURL = themeRootURL.toString();
32
+
33
+ if (themeRootURL.startsWith(".") || themeRootURL.startsWith("/")) {
34
+ // Handle relative url
35
+ // new URL("/newExmPath", "http://example.com/exmPath") => http://example.com/newExmPath
36
+ // new URL("./newExmPath", "http://example.com/exmPath") => http://example.com/exmPath/newExmPath
37
+ // new URL("../newExmPath", "http://example.com/exmPath") => http://example.com/newExmPath
38
+ resultUrl = new URL(themeRootURL, window.location.href).toString();
39
+ } else if (origin && validateThemeOrigin(origin)) {
40
+ // If origin is allowed, use it
41
+ resultUrl = themeRootURL.toString();
42
+ } else {
43
+ // If origin is not allow and the URL is not relative, we have to replace the origin
44
+ // with current location
45
+ resultUrl = buildCorrectUrl(themeRootURL, window.location.href);
46
+ }
47
+
48
+ if (!resultUrl.endsWith("/")) {
49
+ resultUrl = `${resultUrl}/`;
50
+ }
51
+
52
+ return `${resultUrl}UI5/`;
53
+ } catch (e) {
54
+ // Catch if URL is not correct
55
+ }
56
+ };
57
+
58
+ export default validateThemeRoot;
@@ -15,7 +15,7 @@ const eslintConfig = `--config ${require.resolve("@ui5/webcomponents-tools/compo
15
15
  const scripts = {
16
16
  clean: "rimraf dist && rimraf .port",
17
17
  lint: `eslint . ${eslintConfig}`,
18
- prepare: "nps clean integrate copy generateAssetParameters generateVersionInfo generateStyles",
18
+ prepare: "nps clean integrate copy generateAssetParameters generateVersionInfo generateStyles generateTemplates generateAPI",
19
19
  integrate: {
20
20
  default: "nps integrate.copy-used-modules integrate.replace-amd integrate.amd-to-es6 integrate.esm-abs-to-rel integrate.third-party",
21
21
  "copy-used-modules": `node "${copyUsedModules}" ./used-modules.txt dist/`,
@@ -39,6 +39,8 @@ const scripts = {
39
39
  generateAssetParameters: `node "${assetParametersScript}"`,
40
40
  generateVersionInfo: `node "${versionScript}"`,
41
41
  generateStyles: `node "${stylesScript}"`,
42
+ generateTemplates: `mkdirp dist/generated/templates && node "${LIB}/hbs2ui5/index.js" -d test/elements -o dist/generated/templates`,
43
+ generateAPI: `jsdoc -c "${LIB}/jsdoc/config.json"`,
42
44
  watch: {
43
45
  default: 'concurrently "nps watch.src" "nps watch.styles"',
44
46
  withBundle: 'concurrently "nps watch.src" "nps watch.bundle" "nps watch.styles"',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ui5/webcomponents-base",
3
- "version": "1.8.0",
3
+ "version": "1.9.1",
4
4
  "description": "UI5 Web Components: webcomponents.base",
5
5
  "author": "SAP SE (https://www.sap.com)",
6
6
  "license": "Apache-2.0",
@@ -36,8 +36,8 @@
36
36
  "devDependencies": {
37
37
  "@buxlabs/amd-to-es6": "0.16.1",
38
38
  "@openui5/sap.ui.core": "1.101.0",
39
- "@ui5/webcomponents-tools": "1.8.0",
40
- "chromedriver": "105.0.1",
39
+ "@ui5/webcomponents-tools": "1.9.1",
40
+ "chromedriver": "106.0.1",
41
41
  "clean-css": "^5.2.2",
42
42
  "copy-and-watch": "^0.1.5",
43
43
  "cross-env": "^7.0.3",
@@ -1,12 +1,14 @@
1
1
  import merge from "./thirdparty/merge.js";
2
2
  import { getFeature } from "./FeaturesRegistry.js";
3
3
  import { DEFAULT_THEME } from "./generated/AssetParameters.js";
4
+ import validateThemeRoot from "./validateThemeRoot.js";
4
5
 
5
6
  let initialized = false;
6
7
 
7
8
  let initialConfig = {
8
9
  animationMode: "full",
9
10
  theme: DEFAULT_THEME,
11
+ themeRoot: null,
10
12
  rtl: null,
11
13
  language: null,
12
14
  calendarType: null,
@@ -26,6 +28,11 @@ const getTheme = () => {
26
28
  return initialConfig.theme;
27
29
  };
28
30
 
31
+ const getThemeRoot = () => {
32
+ initConfiguration();
33
+ return initialConfig.themeRoot;
34
+ };
35
+
29
36
  const getRTL = () => {
30
37
  initConfiguration();
31
38
  return initialConfig.rtl;
@@ -106,7 +113,13 @@ const parseURLParameters = () => {
106
113
  });
107
114
  };
108
115
 
109
- const normalizeParamValue = (param, value) => {
116
+ const normalizeThemeRootParamValue = value => {
117
+ const themeRoot = value.split("@")[1];
118
+
119
+ return validateThemeRoot(themeRoot);
120
+ };
121
+
122
+ const normalizeThemeParamValue = (param, value) => {
110
123
  if (param === "theme" && value.includes("@")) { // the theme parameter might have @<URL-TO-THEME> in the value - strip this
111
124
  return value.split("@")[0];
112
125
  }
@@ -122,9 +135,15 @@ const applyURLParam = (key, value, paramType) => {
122
135
  value = booleanMapping.get(lowerCaseValue);
123
136
  }
124
137
 
125
- value = normalizeParamValue(param, value);
138
+ if (param === "theme") {
139
+ initialConfig.theme = normalizeThemeParamValue(param, value);
126
140
 
127
- initialConfig[param] = value;
141
+ if (value && value.includes("@")) {
142
+ initialConfig.themeRoot = normalizeThemeRootParamValue(value);
143
+ }
144
+ } else {
145
+ initialConfig[param] = value;
146
+ }
128
147
  };
129
148
 
130
149
  const applyOpenUI5Configuration = () => {
@@ -157,6 +176,7 @@ const initConfiguration = () => {
157
176
  export {
158
177
  getAnimationMode,
159
178
  getTheme,
179
+ getThemeRoot,
160
180
  getRTL,
161
181
  getLanguage,
162
182
  getFetchDefaultLanguage,
@@ -17,6 +17,7 @@ class StaticAreaItem extends HTMLElement {
17
17
  this._rendered = false;
18
18
  this.attachShadow({ mode: "open" });
19
19
  this.pureTagName = "ui5-static-area-item";
20
+ this.popupIntegrationAttr = "data-sap-ui-integration-popup-content";
20
21
  }
21
22
 
22
23
  /**
@@ -37,7 +38,7 @@ class StaticAreaItem extends HTMLElement {
37
38
  */
38
39
  update() {
39
40
  if (this._rendered) {
40
- this.setAttribute(this.pureTagName, "");
41
+ this._updateAdditionalAttrs();
41
42
  this._updateContentDensity();
42
43
  this._updateDirection();
43
44
  updateShadowRoot(this.ownerElement, true);
@@ -67,6 +68,11 @@ class StaticAreaItem extends HTMLElement {
67
68
  }
68
69
  }
69
70
 
71
+ _updateAdditionalAttrs() {
72
+ this.setAttribute(this.pureTagName, "");
73
+ this.setAttribute(this.popupIntegrationAttr, "");
74
+ }
75
+
70
76
  /**
71
77
  * @protected
72
78
  * Returns reference to the DOM element where the current fragment is added.
@@ -1,6 +1,8 @@
1
1
  import getSharedResource from "../getSharedResource.js";
2
2
 
3
+ const loaders = new Map();
3
4
  const registry = getSharedResource("SVGIllustration.registry", new Map());
5
+ const illustrationPromises = getSharedResource("SVGIllustration.promises", new Map());
4
6
  const ILLUSTRATION_NOT_FOUND = "ILLUSTRATION_NOT_FOUND";
5
7
 
6
8
  const registerIllustration = (name, { dialogSvg, sceneSvg, spotSvg, set, title, subtitle } = {}) => { // eslint-disable-line
@@ -13,6 +15,21 @@ const registerIllustration = (name, { dialogSvg, sceneSvg, spotSvg, set, title,
13
15
  });
14
16
  };
15
17
 
18
+ const registerIllustrationLoader = async (illustrationName, loader) => {
19
+ loaders.set(illustrationName, loader);
20
+ };
21
+
22
+ const _loadIllustrationOnce = async illustrationName => {
23
+ if (!illustrationPromises.has(illustrationName)) {
24
+ if (!loaders.has(illustrationName)) {
25
+ throw new Error(`No loader registered for the ${illustrationName} illustration. Probably you forgot to import the "@ui5/webcomponents-fiori/dist/illustrations/AllIllustrations.js" module.`);
26
+ }
27
+ const loadIllustrations = loaders.get(illustrationName);
28
+ illustrationPromises.set(illustrationName, loadIllustrations(illustrationName));
29
+ }
30
+ return illustrationPromises.get(illustrationName);
31
+ };
32
+
16
33
  const getIllustrationDataSync = nameProp => {
17
34
  let set = "fiori";
18
35
 
@@ -20,11 +37,23 @@ const getIllustrationDataSync = nameProp => {
20
37
  set = "tnt";
21
38
  nameProp = nameProp.replace(/^Tnt/, "");
22
39
  }
40
+ return registry.get(`${set}/${nameProp}`);
41
+ };
42
+
43
+ const getIllustrationData = async illustrationName => {
44
+ let set = "fiori";
23
45
 
24
- return registry.get(`${set}/${nameProp}`) || ILLUSTRATION_NOT_FOUND;
46
+ await _loadIllustrationOnce(illustrationName);
47
+ if (illustrationName.startsWith("Tnt")) {
48
+ set = "tnt";
49
+ illustrationName = illustrationName.replace(/^Tnt/, "");
50
+ }
51
+ return registry.get(`${set}/${illustrationName}`) || ILLUSTRATION_NOT_FOUND;
25
52
  };
26
53
 
27
54
  export {
28
55
  getIllustrationDataSync,
29
56
  registerIllustration,
57
+ registerIllustrationLoader,
58
+ getIllustrationData,
30
59
  };
@@ -0,0 +1,39 @@
1
+ import createLinkInHead from "../util/createLinkInHead.js";
2
+ import validateThemeRoot from "../validateThemeRoot.js";
3
+ import { getThemeRoot as getConfiguredThemeRoot } from "../InitialConfiguration.js";
4
+
5
+ let themeRoot;
6
+
7
+ const getThemeRoot = () => {
8
+ if (themeRoot === undefined) {
9
+ themeRoot = getConfiguredThemeRoot();
10
+ }
11
+
12
+ return themeRoot;
13
+ };
14
+
15
+ const setThemeRoot = (theme, newThemeRoot) => {
16
+ themeRoot = validateThemeRoot(newThemeRoot);
17
+
18
+ attachCustomThemeStylesToHead(theme);
19
+ };
20
+
21
+ const formatThemeLink = theme => {
22
+ return `${getThemeRoot()}Base/baseLib/${theme}/css_variables.css`;
23
+ };
24
+
25
+ const attachCustomThemeStylesToHead = async theme => {
26
+ const link = document.querySelector(`[sap-ui-webcomponents-theme="${theme}"]`);
27
+
28
+ if (link) {
29
+ document.head.removeChild(link);
30
+ }
31
+
32
+ await createLinkInHead(formatThemeLink(theme), { "sap-ui-webcomponents-theme": theme });
33
+ };
34
+
35
+ export {
36
+ getThemeRoot,
37
+ setThemeRoot,
38
+ attachCustomThemeStylesToHead,
39
+ };