@ui5/webcomponents-base 1.0.0-rc.15 → 1.0.2

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 (115) hide show
  1. package/.eslintignore +2 -1
  2. package/CHANGELOG.md +53 -0
  3. package/README.md +26 -2
  4. package/bundle.esm.js +6 -2
  5. package/dist/CSP.js +59 -0
  6. package/dist/Device.js +5 -0
  7. package/dist/EventProvider.js +19 -25
  8. package/dist/FontFace.js +7 -95
  9. package/dist/InitialConfiguration.js +11 -7
  10. package/dist/Keys.js +9 -0
  11. package/dist/ManagedStyles.js +83 -0
  12. package/dist/Render.js +3 -1
  13. package/dist/StaticAreaItem.js +11 -9
  14. package/dist/SystemCSSVars.js +4 -25
  15. package/dist/UI5Element.js +43 -59
  16. package/dist/UI5ElementMetadata.js +9 -1
  17. package/dist/asset-registries/Icons.js +26 -8
  18. package/dist/asset-registries/Illustrations.js +10 -3
  19. package/dist/asset-registries/LocaleData.js +11 -2
  20. package/dist/assets-meta/IconCollectionsAlias.js +18 -0
  21. package/dist/config/Theme.js +14 -0
  22. package/dist/css/FontFace.css +45 -0
  23. package/dist/css/OverrideFontFace.css +32 -0
  24. package/dist/css/SystemCSSVars.css +17 -0
  25. package/dist/delegate/ItemNavigation.js +66 -0
  26. package/dist/generated/AssetParameters.js +1 -1
  27. package/dist/generated/css/FontFace.css.js +5 -0
  28. package/dist/generated/css/OverrideFontFace.css.js +5 -0
  29. package/dist/generated/css/SystemCSSVars.css.js +5 -0
  30. package/dist/i18nBundle.js +33 -2
  31. package/dist/renderer/LitRenderer.js +7 -4
  32. package/dist/renderer/directives/style-map.js +72 -0
  33. package/dist/resources/bundle.esm.js +19 -8
  34. package/dist/resources/bundle.esm.js.map +1 -1
  35. package/dist/sap/base/Log.js +2 -10
  36. package/dist/sap/base/assert.js +1 -5
  37. package/dist/test-resources/elements/WithStaticArea.js +2 -1
  38. package/dist/test-resources/pages/AllTestElements.html +3 -0
  39. package/dist/test-resources/pages/i18n.html +1 -3
  40. package/dist/test-resources/specs/ConfigurationChange.spec.js +9 -9
  41. package/dist/test-resources/specs/ConfigurationScript.spec.js +24 -24
  42. package/dist/test-resources/specs/ConfigurationURL.spec.js +33 -33
  43. package/dist/test-resources/specs/CustomTheme.spec.js +7 -7
  44. package/dist/test-resources/specs/EventProvider.spec.js +63 -0
  45. package/dist/test-resources/specs/StaticArea.spec.js +55 -13
  46. package/dist/test-resources/specs/Theming.spec.js +11 -11
  47. package/dist/test-resources/specs/UI5ElementInvalidation.js +29 -29
  48. package/dist/test-resources/specs/UI5ElementLifecycle.js +11 -11
  49. package/dist/test-resources/specs/UI5ElementListenForChildPropChanges.spec.js +11 -11
  50. package/dist/test-resources/specs/UI5ElementMetadataExt.js +8 -8
  51. package/dist/test-resources/specs/UI5ElementPropertyValidation.js +6 -6
  52. package/dist/test-resources/specs/UI5ElementPropsAndAttrs.spec.js +36 -36
  53. package/dist/test-resources/specs/UI5ElementShadowDOM.js +9 -9
  54. package/dist/test-resources/specs/UI5ElementSlots.js +9 -9
  55. package/dist/theming/CustomStyle.js +23 -3
  56. package/dist/theming/applyTheme.js +11 -10
  57. package/dist/theming/getEffectiveLinksHrefs.js +20 -0
  58. package/dist/theming/getStylesString.js +4 -2
  59. package/dist/theming/getThemeDesignerTheme.js +25 -5
  60. package/dist/theming/preloadLinks.js +23 -0
  61. package/dist/types/DataType.js +12 -0
  62. package/dist/types/Float.js +4 -0
  63. package/dist/types/Integer.js +4 -0
  64. package/dist/updateShadowRoot.js +8 -4
  65. package/dist/util/createLinkInHead.js +19 -0
  66. package/dist/util/encodeXML.js +35 -0
  67. package/dist/util/escapeRegex.js +10 -0
  68. package/dist/util/generateHighlightedMarkup.js +42 -0
  69. package/hash.txt +1 -1
  70. package/lib/generate-asset-parameters/index.js +0 -1
  71. package/lib/generate-styles/index.js +18 -0
  72. package/package-scripts.js +9 -6
  73. package/package.json +9 -11
  74. package/src/CSP.js +59 -0
  75. package/src/Device.js +5 -0
  76. package/src/EventProvider.js +19 -25
  77. package/src/FontFace.js +7 -95
  78. package/src/InitialConfiguration.js +11 -7
  79. package/src/Keys.js +9 -0
  80. package/src/ManagedStyles.js +83 -0
  81. package/src/Render.js +3 -1
  82. package/src/StaticAreaItem.js +11 -9
  83. package/src/SystemCSSVars.js +4 -25
  84. package/src/UI5Element.js +43 -59
  85. package/src/UI5ElementMetadata.js +9 -1
  86. package/src/asset-registries/Icons.js +26 -8
  87. package/src/asset-registries/Illustrations.js +10 -3
  88. package/src/asset-registries/LocaleData.js +11 -2
  89. package/src/assets-meta/IconCollectionsAlias.js +18 -0
  90. package/src/config/Theme.js +14 -0
  91. package/src/css/FontFace.css +45 -0
  92. package/src/css/OverrideFontFace.css +32 -0
  93. package/src/css/SystemCSSVars.css +17 -0
  94. package/src/delegate/ItemNavigation.js +66 -0
  95. package/src/i18nBundle.js +33 -2
  96. package/src/renderer/LitRenderer.js +7 -4
  97. package/src/renderer/directives/style-map.js +72 -0
  98. package/src/theming/CustomStyle.js +23 -3
  99. package/src/theming/applyTheme.js +11 -10
  100. package/src/theming/getEffectiveLinksHrefs.js +20 -0
  101. package/src/theming/getStylesString.js +4 -2
  102. package/src/theming/getThemeDesignerTheme.js +25 -5
  103. package/src/theming/preloadLinks.js +23 -0
  104. package/src/types/DataType.js +12 -0
  105. package/src/types/Float.js +4 -0
  106. package/src/types/Integer.js +4 -0
  107. package/src/updateShadowRoot.js +8 -4
  108. package/src/util/createLinkInHead.js +19 -0
  109. package/src/util/encodeXML.js +35 -0
  110. package/src/util/escapeRegex.js +10 -0
  111. package/src/util/generateHighlightedMarkup.js +42 -0
  112. package/dist/config/AssetsPath.js +0 -17
  113. package/dist/theming/createThemePropertiesStyleTag.js +0 -20
  114. package/src/config/AssetsPath.js +0 -17
  115. package/src/theming/createThemePropertiesStyleTag.js +0 -20
package/src/FontFace.js CHANGED
@@ -1,95 +1,7 @@
1
- /**
2
- * CSS font face used for the texts provided by SAP.
3
- */
4
- import createStyleInHead from "./util/createStyleInHead.js";
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 fontFaceCSS = `
21
- @font-face {
22
- font-family: "72";
23
- font-style: normal;
24
- font-weight: 400;
25
- src: local("72"),
26
- url(${font72RegularWoff2}) format("woff2"),
27
- url(${font72RegularWoff}) format("woff");
28
- }
29
-
30
- @font-face {
31
- font-family: "72full";
32
- font-style: normal;
33
- font-weight: 400;
34
- src: local('72-full'),
35
- url(${font72RegularFullWoff2}) format("woff2"),
36
- url(${font72RegularFullWoff}) format("woff");
37
-
38
- }
39
-
40
- @font-face {
41
- font-family: "72";
42
- font-style: normal;
43
- font-weight: 700;
44
- src: local('72-Bold'),
45
- url(${font72BoldWoff2}) format("woff2"),
46
- url(${font72BoldWoff}) format("woff");
47
- }
48
-
49
- @font-face {
50
- font-family: "72full";
51
- font-style: normal;
52
- font-weight: 700;
53
- src: local('72-Bold-full'),
54
- url(${font72BoldFullWoff2}) format("woff2"),
55
- url(${font72BoldFullWoff}) format("woff");
56
- }
57
- `;
58
-
59
- /**
60
- * Some diacritics are supported by the 72 font:
61
- * * Grave
62
- * * Acute
63
- * * Circumflex
64
- * * Tilde
65
- *
66
- * However, the following diacritics and the combination of multiple diacritics (including the supported ones) are not supported:
67
- * * Breve
68
- * * Horn
69
- * * Dot below
70
- * * Hook above
71
- *
72
- *
73
- * Override for the characters that aren't covered by the '72' font to other system fonts
74
- *
75
- * U+0102-0103: A and a with Breve
76
- * U+01A0-01A1: O and o with Horn
77
- * U+01AF-01B0: U and u with Horn
78
- * U+1EA0-1EB7: A and a with diacritics that are not supported by the font and combination of multiple diacritics
79
- * U+1EB8-1EC7: E and e with diacritics that are not supported by the font and combination of multiple diacritics
80
- * U+1EC8-1ECB: I and i with diacritics that are not supported by the font and combination of multiple diacritics
81
- * U+1ECC-1EE3: O and o with diacritics that are not supported by the font and combination of multiple diacritics
82
- * U+1EE4-1EF1: U and u with diacritics that are not supported by the font and combination of multiple diacritics
83
- * U+1EF4-1EF7: Y and y with diacritics that are not supported by the font and combination of multiple diacritics
84
- *
85
- */
86
- const overrideFontFaceCSS = `
87
- @font-face {
88
- font-family: '72override';
89
- 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;
90
- src: local('Arial'), local('Helvetica'), local('sans-serif');
91
- }
92
- `;
3
+ import fontFaceCSS from "./generated/css/FontFace.css.js";
4
+ import overrideFontFaceCSS from "./generated/css/OverrideFontFace.css.js";
93
5
 
94
6
  const insertFontFace = () => {
95
7
  const OpenUI5Support = getFeature("OpenUI5Support");
@@ -104,14 +16,14 @@ const insertFontFace = () => {
104
16
  };
105
17
 
106
18
  const insertMainFontFace = () => {
107
- if (!document.querySelector(`head>style[data-ui5-font-face]`)) {
108
- createStyleInHead(fontFaceCSS, { "data-ui5-font-face": "" });
19
+ if (!hasStyle("data-ui5-font-face")) {
20
+ createStyle(fontFaceCSS, "data-ui5-font-face");
109
21
  }
110
22
  };
111
23
 
112
24
  const insertOverrideFontFace = () => {
113
- if (!document.querySelector(`head>style[data-ui5-font-face-override]`)) {
114
- createStyleInHead(overrideFontFaceCSS, { "data-ui5-font-face-override": "" });
25
+ if (!hasStyle("data-ui5-font-face-override")) {
26
+ createStyle(overrideFontFaceCSS, "data-ui5-font-face-override");
115
27
  }
116
28
  };
117
29
 
@@ -13,7 +13,6 @@ let initialConfig = {
13
13
  noConflict: false, // no URL
14
14
  formatSettings: {},
15
15
  fetchDefaultLanguage: false,
16
- assetsPath: "",
17
16
  };
18
17
 
19
18
  /* General settings */
@@ -62,11 +61,6 @@ const getFormatSettings = () => {
62
61
  return initialConfig.formatSettings;
63
62
  };
64
63
 
65
- const getAssetsPath = () => {
66
- initConfiguration();
67
- return initialConfig.assetsPath;
68
- };
69
-
70
64
  const booleanMapping = new Map();
71
65
  booleanMapping.set("true", true);
72
66
  booleanMapping.set("false", false);
@@ -112,6 +106,14 @@ const parseURLParameters = () => {
112
106
  });
113
107
  };
114
108
 
109
+ const normalizeParamValue = (param, value) => {
110
+ if (param === "theme" && value.includes("@")) { // the theme parameter might have @<URL-TO-THEME> in the value - strip this
111
+ return value.split("@")[0];
112
+ }
113
+
114
+ return value;
115
+ };
116
+
115
117
  const applyURLParam = (key, value, paramType) => {
116
118
  const lowerCaseValue = value.toLowerCase();
117
119
  const param = key.split(`${paramType}-`)[1];
@@ -119,6 +121,9 @@ const applyURLParam = (key, value, paramType) => {
119
121
  if (booleanMapping.has(value)) {
120
122
  value = booleanMapping.get(lowerCaseValue);
121
123
  }
124
+
125
+ value = normalizeParamValue(param, value);
126
+
122
127
  initialConfig[param] = value;
123
128
  };
124
129
 
@@ -158,5 +163,4 @@ export {
158
163
  getNoConflict,
159
164
  getCalendarType,
160
165
  getFormatSettings,
161
- getAssetsPath,
162
166
  };
package/src/Keys.js CHANGED
@@ -163,8 +163,12 @@ const isPageDown = event => (event.key ? event.key === "PageDown" : event.keyCod
163
163
 
164
164
  const isPageUpShift = event => (event.key ? event.key === "PageUp" : event.keyCode === KeyCodes.PAGE_UP) && checkModifierKeys(event, false, false, true);
165
165
 
166
+ const isPageUpAlt = event => (event.key ? event.key === "PageUp" : event.keyCode === KeyCodes.PAGE_UP) && checkModifierKeys(event, false, true, false);
167
+
166
168
  const isPageDownShift = event => (event.key ? event.key === "PageDown" : event.keyCode === KeyCodes.PAGE_DOWN) && checkModifierKeys(event, false, false, true);
167
169
 
170
+ const isPageDownAlt = event => (event.key ? event.key === "PageDown" : event.keyCode === KeyCodes.PAGE_DOWN) && checkModifierKeys(event, false, true, false);
171
+
168
172
  const isPageUpShiftCtrl = event => (event.key ? event.key === "PageUp" : event.keyCode === KeyCodes.PAGE_UP) && checkModifierKeys(event, true, false, true);
169
173
 
170
174
  const isPageDownShiftCtrl = event => (event.key ? event.key === "PageDown" : event.keyCode === KeyCodes.PAGE_DOWN) && checkModifierKeys(event, true, false, true);
@@ -187,6 +191,8 @@ const isF4 = event => {
187
191
 
188
192
  const isF4Shift = event => (event.key ? event.key === "F4" : event.keyCode === KeyCodes.F4) && checkModifierKeys(event, false, false, true);
189
193
 
194
+ const isF7 = event => (event.key ? event.key === "F7" : event.keyCode === KeyCodes.F7) && !hasModifierKeys(event);
195
+
190
196
  const isShowByArrows = event => {
191
197
  return ((event.key === "ArrowDown" || event.key === "Down") || (event.key === "ArrowUp" || event.key === "Up")) && checkModifierKeys(event, /* Ctrl */ false, /* Alt */ true, /* Shift */ false);
192
198
  };
@@ -230,10 +236,13 @@ export {
230
236
  isShow,
231
237
  isF4,
232
238
  isF4Shift,
239
+ isF7,
233
240
  isPageUp,
234
241
  isPageDown,
235
242
  isPageUpShift,
243
+ isPageUpAlt,
236
244
  isPageDownShift,
245
+ isPageDownAlt,
237
246
  isPageUpShiftCtrl,
238
247
  isPageDownShiftCtrl,
239
248
  };
@@ -0,0 +1,83 @@
1
+ import createStyleInHead from "./util/createStyleInHead.js";
2
+ import createLinkInHead from "./util/createLinkInHead.js";
3
+ import { shouldUseLinks, getUrl } from "./CSP.js";
4
+
5
+ const getStyleId = (name, value) => {
6
+ return value ? `${name}|${value}` : name;
7
+ };
8
+
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) {
18
+ const stylesheet = new CSSStyleSheet();
19
+ stylesheet.replaceSync(content);
20
+ stylesheet._ui5StyleId = getStyleId(name, value); // set an id so that we can find the style later
21
+ document.adoptedStyleSheets = [...document.adoptedStyleSheets, stylesheet];
22
+ } else {
23
+ const attributes = {};
24
+ attributes[name] = value;
25
+ createStyleInHead(content, attributes);
26
+ }
27
+ };
28
+
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) {
35
+ document.adoptedStyleSheets.find(sh => sh._ui5StyleId === getStyleId(name, value)).replaceSync(content || "");
36
+ } else {
37
+ document.querySelector(`head>style[${name}="${value}"]`).textContent = content || "";
38
+ }
39
+ };
40
+
41
+ const hasStyle = (name, value = "") => {
42
+ if (shouldUseLinks()) {
43
+ return !!document.querySelector(`head>link[${name}="${value}"]`);
44
+ }
45
+
46
+ if (document.adoptedStyleSheets) {
47
+ return !!document.adoptedStyleSheets.find(sh => sh._ui5StyleId === getStyleId(name, value));
48
+ }
49
+
50
+ return !!document.querySelector(`head>style[${name}="${value}"]`);
51
+ };
52
+
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
  });
@@ -3,6 +3,7 @@ import updateShadowRoot from "./updateShadowRoot.js";
3
3
  import { renderFinished } from "./Render.js";
4
4
  import getEffectiveContentDensity from "./util/getEffectiveContentDensity.js";
5
5
  import { getEffectiveScopingSuffixForTag } from "./CustomElementsScope.js";
6
+ import getEffectiveDir from "./locale/getEffectiveDir.js";
6
7
 
7
8
  /**
8
9
  *
@@ -33,6 +34,7 @@ class StaticAreaItem extends HTMLElement {
33
34
  update() {
34
35
  if (this._rendered) {
35
36
  this._updateContentDensity();
37
+ this._updateDirection();
36
38
  updateShadowRoot(this.ownerElement, true);
37
39
  }
38
40
  }
@@ -51,6 +53,15 @@ class StaticAreaItem extends HTMLElement {
51
53
  }
52
54
  }
53
55
 
56
+ _updateDirection() {
57
+ const dir = getEffectiveDir(this.ownerElement);
58
+ if (dir) {
59
+ this.setAttribute("dir", dir);
60
+ } else {
61
+ this.removeAttribute("dir");
62
+ }
63
+ }
64
+
54
65
  /**
55
66
  * @protected
56
67
  * Returns reference to the DOM element where the current fragment is added.
@@ -65,15 +76,6 @@ class StaticAreaItem extends HTMLElement {
65
76
  return this.shadowRoot;
66
77
  }
67
78
 
68
- /**
69
- * @protected
70
- * @param refName
71
- * @returns {Element}
72
- */
73
- getStableDomRef(refName) {
74
- return this.shadowRoot.querySelector(`[data-ui5-stable=${refName}]`);
75
- }
76
-
77
79
  static getTag() {
78
80
  const pureTag = "ui5-static-area-item";
79
81
  const suffix = getEffectiveScopingSuffixForTag(pureTag);
@@ -1,31 +1,10 @@
1
- import createStyleInHead from "./util/createStyleInHead.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
- `;
1
+ import { hasStyle, createStyle } from "./ManagedStyles.js";
2
+ import systemCSSVars from "./generated/css/SystemCSSVars.css.js";
22
3
 
23
4
  const insertSystemCSSVars = () => {
24
- if (document.querySelector(`head>style[data-ui5-system-css-vars]`)) {
25
- return;
5
+ if (!hasStyle("data-ui5-system-css-vars")) {
6
+ createStyle(systemCSSVars, "data-ui5-system-css-vars");
26
7
  }
27
-
28
- createStyleInHead(systemCSSVars, { "data-ui5-system-css-vars": "" });
29
8
  };
30
9
 
31
10
  export default insertSystemCSSVars;
package/src/UI5Element.js CHANGED
@@ -10,15 +10,15 @@ import { registerTag, isTagRegistered, recordTagRegistrationFailure } from "./Cu
10
10
  import { observeDOMNode, unobserveDOMNode } from "./DOMObserver.js";
11
11
  import { skipOriginalEvent } from "./config/NoConflict.js";
12
12
  import getEffectiveDir from "./locale/getEffectiveDir.js";
13
- import Integer from "./types/Integer.js";
14
- import Float from "./types/Float.js";
13
+ import DataType from "./types/DataType.js";
15
14
  import { kebabToCamelCase, camelToKebabCase } from "./util/StringHelper.js";
16
15
  import isValidPropertyName from "./util/isValidPropertyName.js";
16
+ import isDescendantOf from "./util/isDescendantOf.js";
17
17
  import { isSlot, getSlotName, getSlottedElementsList } from "./util/SlotsHelper.js";
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
 
@@ -43,7 +43,7 @@ function _invalidate(changeInfo) {
43
43
 
44
44
  this._changedState.push(changeInfo);
45
45
  renderDeferred(this);
46
- this._eventProvider.fireEvent("change", { ...changeInfo, target: this });
46
+ this._eventProvider.fireEvent("invalidate", { ...changeInfo, target: this });
47
47
  }
48
48
 
49
49
  /**
@@ -102,7 +102,6 @@ class UI5Element extends HTMLElement {
102
102
  async connectedCallback() {
103
103
  this.setAttribute(this.constructor.getMetadata().getPureTag(), "");
104
104
 
105
- const needsShadowDOM = this.constructor._needsShadowDOM();
106
105
  const slotsAreManaged = this.constructor.getMetadata().slotsAreManaged();
107
106
 
108
107
  this._inDOM = true;
@@ -113,10 +112,6 @@ class UI5Element extends HTMLElement {
113
112
  await this._processChildren();
114
113
  }
115
114
 
116
- if (needsShadowDOM && !this.shadowRoot) { // Workaround for Firefox74 bug
117
- await Promise.resolve();
118
- }
119
-
120
115
  if (!this._inDOM) { // Component removed from DOM while _processChildren was running
121
116
  return;
122
117
  }
@@ -134,7 +129,6 @@ class UI5Element extends HTMLElement {
134
129
  * @private
135
130
  */
136
131
  disconnectedCallback() {
137
- const needsShadowDOM = this.constructor._needsShadowDOM();
138
132
  const slotsAreManaged = this.constructor.getMetadata().slotsAreManaged();
139
133
 
140
134
  this._inDOM = false;
@@ -143,13 +137,11 @@ class UI5Element extends HTMLElement {
143
137
  this._stopObservingDOMChildren();
144
138
  }
145
139
 
146
- if (needsShadowDOM) {
147
- if (this._fullyConnected) {
148
- if (typeof this.onExitDOM === "function") {
149
- this.onExitDOM();
150
- }
151
- this._fullyConnected = false;
140
+ if (this._fullyConnected) {
141
+ if (typeof this.onExitDOM === "function") {
142
+ this.onExitDOM();
152
143
  }
144
+ this._fullyConnected = false;
153
145
  }
154
146
 
155
147
  if (this.staticAreaItem && this.staticAreaItem.parentElement) {
@@ -259,7 +251,7 @@ class UI5Element extends HTMLElement {
259
251
 
260
252
  // Listen for any invalidation on the child if invalidateOnChildChange is true or an object (ignore when false or not set)
261
253
  if (child.isUI5Element && slotData.invalidateOnChildChange) {
262
- child._attachChange(this._getChildChangeListener(slotName));
254
+ child.attachInvalidate(this._getChildChangeListener(slotName));
263
255
  }
264
256
 
265
257
  // Listen for the slotchange event if the child is a slot itself
@@ -319,7 +311,7 @@ class UI5Element extends HTMLElement {
319
311
 
320
312
  children.forEach(child => {
321
313
  if (child && child.isUI5Element) {
322
- child._detachChange(this._getChildChangeListener(slotName));
314
+ child.detachInvalidate(this._getChildChangeListener(slotName));
323
315
  }
324
316
 
325
317
  if (isSlot(child)) {
@@ -334,20 +326,20 @@ class UI5Element extends HTMLElement {
334
326
  * Attach a callback that will be executed whenever the component is invalidated
335
327
  *
336
328
  * @param callback
337
- * @protected
329
+ * @public
338
330
  */
339
- _attachChange(callback) {
340
- this._eventProvider.attachEvent("change", callback);
331
+ attachInvalidate(callback) {
332
+ this._eventProvider.attachEvent("invalidate", callback);
341
333
  }
342
334
 
343
335
  /**
344
336
  * Detach the callback that is executed whenever the component is invalidated
345
337
  *
346
338
  * @param callback
347
- * @protected
339
+ * @public
348
340
  */
349
- _detachChange(callback) {
350
- this._eventProvider.detachEvent("change", callback);
341
+ detachInvalidate(callback) {
342
+ this._eventProvider.detachEvent("invalidate", callback);
351
343
  }
352
344
 
353
345
  /**
@@ -384,12 +376,8 @@ class UI5Element extends HTMLElement {
384
376
  const propertyTypeClass = properties[nameInCamelCase].type;
385
377
  if (propertyTypeClass === Boolean) {
386
378
  newValue = newValue !== null;
387
- }
388
- if (propertyTypeClass === Integer) {
389
- newValue = parseInt(newValue);
390
- }
391
- if (propertyTypeClass === Float) {
392
- newValue = parseFloat(newValue);
379
+ } else if (isDescendantOf(propertyTypeClass, DataType)) {
380
+ newValue = propertyTypeClass.attributeToProperty(newValue);
393
381
  }
394
382
  this[nameInCamelCase] = newValue;
395
383
  }
@@ -402,22 +390,24 @@ class UI5Element extends HTMLElement {
402
390
  if (!this.constructor.getMetadata().hasAttribute(name)) {
403
391
  return;
404
392
  }
405
-
406
- if (typeof newValue === "object") {
407
- return;
408
- }
409
-
393
+ const properties = this.constructor.getMetadata().getProperties();
394
+ const propertyTypeClass = properties[name].type;
410
395
  const attrName = camelToKebabCase(name);
411
396
  const attrValue = this.getAttribute(attrName);
412
- if (typeof newValue === "boolean") {
397
+
398
+ if (propertyTypeClass === Boolean) {
413
399
  if (newValue === true && attrValue === null) {
414
400
  this.setAttribute(attrName, "");
415
401
  } else if (newValue === false && attrValue !== null) {
416
402
  this.removeAttribute(attrName);
417
403
  }
418
- } else if (attrValue !== newValue) {
419
- this.setAttribute(attrName, newValue);
420
- }
404
+ } else if (isDescendantOf(propertyTypeClass, DataType)) {
405
+ this.setAttribute(attrName, propertyTypeClass.propertyToAttribute(newValue));
406
+ } else if (typeof newValue !== "object") {
407
+ if (attrValue !== newValue) {
408
+ this.setAttribute(attrName, newValue);
409
+ }
410
+ } // else { return; } // old object handling
421
411
  }
422
412
 
423
413
  /**
@@ -617,25 +607,27 @@ class UI5Element extends HTMLElement {
617
607
 
618
608
  /**
619
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
620
611
  * Use this method instead of "this.shadowRoot" to read the Shadow DOM, if ever necessary
612
+ *
621
613
  * @public
622
614
  */
623
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
+
624
621
  if (!this.shadowRoot || this.shadowRoot.children.length === 0) {
625
622
  return;
626
623
  }
627
624
 
628
- this._assertShadowRootStructure();
629
-
630
- return this.shadowRoot.children.length === 1
631
- ? this.shadowRoot.children[0] : this.shadowRoot.children[1];
632
- }
633
-
634
- _assertShadowRootStructure() {
635
- const expectedChildrenCount = document.adoptedStyleSheets || isLegacyBrowser() ? 1 : 2;
636
- if (this.shadowRoot.children.length !== expectedChildrenCount) {
625
+ const children = [...this.shadowRoot.children].filter(child => !["link", "style"].includes(child.localName));
626
+ if (children.length !== 1) {
637
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
638
628
  }
629
+
630
+ return children[0];
639
631
  }
640
632
 
641
633
  /**
@@ -661,17 +653,6 @@ class UI5Element extends HTMLElement {
661
653
  return this.getFocusDomRef();
662
654
  }
663
655
 
664
- /**
665
- * 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
666
- * @public
667
- * @method
668
- * @param {String} refName Defines the name of the stable DOM ref
669
- */
670
- getStableDomRef(refName) {
671
- const staticAreaResult = this.staticAreaItem && this.staticAreaItem.getStableDomRef(refName);
672
- return staticAreaResult || this.getDomRef().querySelector(`[data-ui5-stable=${refName}]`);
673
- }
674
-
675
656
  /**
676
657
  * Set the focus to the element, returned by "getFocusDomRef()" (marked by "data-sap-focus-ref")
677
658
  * @public
@@ -861,6 +842,8 @@ class UI5Element extends HTMLElement {
861
842
  const oldState = this._state[prop];
862
843
  if (propData.multiple && propData.compareValues) {
863
844
  isDifferent = !arraysAreEqual(oldState, value);
845
+ } else if (isDescendantOf(propData.type, DataType)) {
846
+ isDifferent = !propData.type.valuesAreEqual(oldState, value);
864
847
  } else {
865
848
  isDifferent = oldState !== value;
866
849
  }
@@ -996,6 +979,7 @@ class UI5Element extends HTMLElement {
996
979
  this._generateAccessors();
997
980
  registerTag(tag);
998
981
  window.customElements.define(tag, this);
982
+ preloadLinks(this);
999
983
 
1000
984
  if (altTag && !customElements.get(altTag)) {
1001
985
  registerTag(altTag);
@@ -126,7 +126,7 @@ class UI5ElementMetadata {
126
126
  */
127
127
  hasAttribute(propName) {
128
128
  const propData = this.getProperties()[propName];
129
- return propData.type !== Object && !propData.noAttribute;
129
+ return propData.type !== Object && !propData.noAttribute && !propData.multiple;
130
130
  }
131
131
 
132
132
  /**
@@ -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