@ui5/webcomponents-base 0.0.0-cc312800a → 0.0.0-cf069fb29

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 (160) hide show
  1. package/.eslintignore +4 -1
  2. package/CHANGELOG.md +107 -0
  3. package/README.md +26 -2
  4. package/bundle.esm.js +6 -2
  5. package/dist/Boot.js +32 -14
  6. package/dist/CSP.js +59 -0
  7. package/dist/CustomElementsRegistry.js +60 -4
  8. package/dist/Device.js +17 -1
  9. package/dist/EventProvider.js +19 -25
  10. package/dist/FeaturesRegistry.js +4 -1
  11. package/dist/FontFace.js +7 -95
  12. package/dist/InitialConfiguration.js +31 -14
  13. package/dist/Keys.js +38 -0
  14. package/dist/ManagedStyles.js +83 -0
  15. package/dist/Render.js +3 -1
  16. package/dist/Runtimes.js +107 -0
  17. package/dist/StaticAreaItem.js +14 -9
  18. package/dist/SystemCSSVars.js +4 -25
  19. package/dist/UI5Element.js +48 -59
  20. package/dist/UI5ElementMetadata.js +17 -1
  21. package/dist/asset-registries/Icons.js +29 -8
  22. package/dist/asset-registries/Illustrations.js +30 -0
  23. package/dist/asset-registries/LocaleData.js +11 -2
  24. package/dist/assets-meta/IconCollectionsAlias.js +18 -0
  25. package/dist/config/Theme.js +14 -0
  26. package/dist/css/FontFace.css +45 -0
  27. package/dist/css/OverrideFontFace.css +32 -0
  28. package/dist/css/SystemCSSVars.css +17 -0
  29. package/dist/delegate/ItemNavigation.js +66 -0
  30. package/dist/delegate/ScrollEnablement.js +7 -1
  31. package/dist/features/F6Navigation.js +106 -0
  32. package/dist/generated/AssetParameters.js +1 -1
  33. package/dist/generated/VersionInfo.js +10 -0
  34. package/dist/generated/css/FontFace.css.js +5 -0
  35. package/dist/generated/css/OverrideFontFace.css.js +5 -0
  36. package/dist/generated/css/SystemCSSVars.css.js +5 -0
  37. package/dist/i18nBundle.js +33 -2
  38. package/dist/renderer/LitRenderer.js +24 -21
  39. package/dist/renderer/directives/style-map.js +72 -0
  40. package/dist/resources/bundle.esm.js +17 -101
  41. package/dist/resources/bundle.esm.js.map +1 -1
  42. package/dist/sap/base/Log.js +241 -0
  43. package/dist/sap/base/assert.js +8 -0
  44. package/dist/sap/base/security/URLListValidator.js +148 -0
  45. package/dist/sap/base/security/encodeCSS.js +14 -0
  46. package/dist/sap/base/security/encodeXML.js +23 -0
  47. package/dist/sap/base/security/sanitizeHTML.js +16 -0
  48. package/dist/sap/base/strings/toHex.js +8 -0
  49. package/dist/sap/base/util/now.js +7 -0
  50. package/dist/sap/ui/thirdparty/caja-html-sanitizer.js +3585 -0
  51. package/dist/test-resources/elements/WithStaticArea.js +2 -1
  52. package/dist/test-resources/pages/AllTestElements.html +3 -0
  53. package/dist/test-resources/pages/i18n.html +1 -3
  54. package/dist/test-resources/specs/ConfigurationChange.spec.js +9 -9
  55. package/dist/test-resources/specs/ConfigurationScript.spec.js +24 -24
  56. package/dist/test-resources/specs/ConfigurationURL.spec.js +64 -18
  57. package/dist/test-resources/specs/CustomTheme.spec.js +7 -7
  58. package/dist/test-resources/specs/EventProvider.spec.js +63 -0
  59. package/dist/test-resources/specs/StaticArea.spec.js +55 -13
  60. package/dist/test-resources/specs/Theming.spec.js +11 -11
  61. package/dist/test-resources/specs/UI5ElementInvalidation.js +29 -29
  62. package/dist/test-resources/specs/UI5ElementLifecycle.js +11 -11
  63. package/dist/test-resources/specs/UI5ElementListenForChildPropChanges.spec.js +11 -11
  64. package/dist/test-resources/specs/UI5ElementMetadataExt.js +8 -8
  65. package/dist/test-resources/specs/UI5ElementPropertyValidation.js +6 -6
  66. package/dist/test-resources/specs/UI5ElementPropsAndAttrs.spec.js +36 -36
  67. package/dist/test-resources/specs/UI5ElementShadowDOM.js +9 -9
  68. package/dist/test-resources/specs/UI5ElementSlots.js +9 -9
  69. package/dist/theming/CustomStyle.js +23 -3
  70. package/dist/theming/applyTheme.js +11 -10
  71. package/dist/theming/getEffectiveLinksHrefs.js +20 -0
  72. package/dist/theming/getStylesString.js +4 -2
  73. package/dist/theming/getThemeDesignerTheme.js +25 -5
  74. package/dist/theming/preloadLinks.js +23 -0
  75. package/dist/types/DataType.js +12 -0
  76. package/dist/types/Float.js +4 -0
  77. package/dist/types/Integer.js +4 -0
  78. package/dist/types/InvisibleMessageMode.js +30 -0
  79. package/dist/updateShadowRoot.js +8 -4
  80. package/dist/util/AriaLabelHelper.js +4 -4
  81. package/dist/util/FocusableElements.js +13 -7
  82. package/dist/util/HTMLSanitizer.js +7 -0
  83. package/dist/util/InvisibleMessage.js +58 -0
  84. package/dist/util/PopupUtils.js +1 -1
  85. package/dist/util/TabbableElements.js +1 -1
  86. package/dist/util/createLinkInHead.js +19 -0
  87. package/dist/util/escapeRegex.js +10 -0
  88. package/dist/util/generateHighlightedMarkup.js +42 -0
  89. package/dist/util/isNodeHidden.js +1 -1
  90. package/dist/util/isNodeTabbable.js +4 -4
  91. package/hash.txt +1 -1
  92. package/index.js +1 -1
  93. package/lib/generate-asset-parameters/index.js +0 -1
  94. package/lib/generate-styles/index.js +18 -0
  95. package/lib/generate-version-info/index.js +27 -0
  96. package/package-scripts.js +27 -3
  97. package/package.json +16 -8
  98. package/src/Boot.js +32 -14
  99. package/src/CSP.js +59 -0
  100. package/src/CustomElementsRegistry.js +60 -4
  101. package/src/Device.js +17 -1
  102. package/src/EventProvider.js +19 -25
  103. package/src/FeaturesRegistry.js +4 -1
  104. package/src/FontFace.js +7 -95
  105. package/src/InitialConfiguration.js +31 -14
  106. package/src/Keys.js +38 -0
  107. package/src/ManagedStyles.js +83 -0
  108. package/src/Render.js +3 -1
  109. package/src/Runtimes.js +107 -0
  110. package/src/StaticAreaItem.js +14 -9
  111. package/src/SystemCSSVars.js +4 -25
  112. package/src/UI5Element.js +48 -59
  113. package/src/UI5ElementMetadata.js +17 -1
  114. package/src/asset-registries/Icons.js +29 -8
  115. package/src/asset-registries/Illustrations.js +30 -0
  116. package/src/asset-registries/LocaleData.js +11 -2
  117. package/src/assets-meta/IconCollectionsAlias.js +18 -0
  118. package/src/config/Theme.js +14 -0
  119. package/src/css/FontFace.css +45 -0
  120. package/src/css/OverrideFontFace.css +32 -0
  121. package/src/css/SystemCSSVars.css +17 -0
  122. package/src/delegate/ItemNavigation.js +66 -0
  123. package/src/delegate/ScrollEnablement.js +7 -1
  124. package/src/features/F6Navigation.js +106 -0
  125. package/src/i18nBundle.js +33 -2
  126. package/src/renderer/LitRenderer.js +24 -21
  127. package/src/renderer/directives/style-map.js +72 -0
  128. package/src/theming/CustomStyle.js +23 -3
  129. package/src/theming/applyTheme.js +11 -10
  130. package/src/theming/getEffectiveLinksHrefs.js +20 -0
  131. package/src/theming/getStylesString.js +4 -2
  132. package/src/theming/getThemeDesignerTheme.js +25 -5
  133. package/src/theming/preloadLinks.js +23 -0
  134. package/src/types/DataType.js +12 -0
  135. package/src/types/Float.js +4 -0
  136. package/src/types/Integer.js +4 -0
  137. package/src/types/InvisibleMessageMode.js +30 -0
  138. package/src/updateShadowRoot.js +8 -4
  139. package/src/util/AriaLabelHelper.js +4 -4
  140. package/src/util/FocusableElements.js +13 -7
  141. package/src/util/HTMLSanitizer.js +7 -0
  142. package/src/util/InvisibleMessage.js +58 -0
  143. package/src/util/PopupUtils.js +1 -1
  144. package/src/util/TabbableElements.js +1 -1
  145. package/src/util/createLinkInHead.js +19 -0
  146. package/src/util/escapeRegex.js +10 -0
  147. package/src/util/generateHighlightedMarkup.js +42 -0
  148. package/src/util/isNodeHidden.js +1 -1
  149. package/src/util/isNodeTabbable.js +4 -4
  150. package/used-modules.txt +10 -0
  151. package/dist/config/AssetsPath.js +0 -17
  152. package/dist/renderer/ifDefined.js +0 -21
  153. package/dist/renderer/scopeHTML.js +0 -32
  154. package/dist/theming/createThemePropertiesStyleTag.js +0 -20
  155. package/dist/util/encodeCSS.js +0 -24
  156. package/src/config/AssetsPath.js +0 -17
  157. package/src/renderer/ifDefined.js +0 -21
  158. package/src/renderer/scopeHTML.js +0 -32
  159. package/src/theming/createThemePropertiesStyleTag.js +0 -20
  160. package/src/util/encodeCSS.js +0 -24
package/src/Keys.js CHANGED
@@ -131,6 +131,18 @@ const isUpShift = event => (event.key ? (event.key === "ArrowUp" || event.key ==
131
131
 
132
132
  const isDownShift = event => (event.key ? (event.key === "ArrowDown" || event.key === "Down") : event.keyCode === KeyCodes.ARROW_DOWN) && checkModifierKeys(event, false, false, true);
133
133
 
134
+ const isUpAlt = event => (event.key ? (event.key === "ArrowUp" || event.key === "Up") : event.keyCode === KeyCodes.ARROW_UP) && checkModifierKeys(event, false, true, false);
135
+
136
+ const isDownAlt = event => (event.key ? (event.key === "ArrowDown" || event.key === "Down") : event.keyCode === KeyCodes.ARROW_DOWN) && checkModifierKeys(event, false, true, false);
137
+
138
+ const isLeftShift = event => (event.key ? (event.key === "ArrowLeft" || event.key === "Left") : event.keyCode === KeyCodes.ARROW_LEFT) && checkModifierKeys(event, false, false, true);
139
+
140
+ const isRightShift = event => (event.key ? (event.key === "ArrowRight" || event.key === "Right") : event.keyCode === KeyCodes.ARROW_RIGHT) && checkModifierKeys(event, false, false, true);
141
+
142
+ const isLeftShiftCtrl = event => (event.key ? (event.key === "ArrowLeft" || event.key === "Left") : event.keyCode === KeyCodes.ARROW_LEFT) && checkModifierKeys(event, true, false, true);
143
+
144
+ const isRightShiftCtrl = event => (event.key ? (event.key === "ArrowRight" || event.key === "Right") : event.keyCode === KeyCodes.ARROW_RIGHT) && checkModifierKeys(event, true, false, true);
145
+
134
146
  const isUpShiftCtrl = event => (event.key ? (event.key === "ArrowUp" || event.key === "Up") : event.keyCode === KeyCodes.ARROW_UP) && checkModifierKeys(event, true, false, true);
135
147
 
136
148
  const isDownShiftCtrl = event => (event.key ? (event.key === "ArrowDown" || event.key === "Down") : event.keyCode === KeyCodes.ARROW_DOWN) && checkModifierKeys(event, true, false, true);
@@ -159,8 +171,12 @@ const isPageDown = event => (event.key ? event.key === "PageDown" : event.keyCod
159
171
 
160
172
  const isPageUpShift = event => (event.key ? event.key === "PageUp" : event.keyCode === KeyCodes.PAGE_UP) && checkModifierKeys(event, false, false, true);
161
173
 
174
+ const isPageUpAlt = event => (event.key ? event.key === "PageUp" : event.keyCode === KeyCodes.PAGE_UP) && checkModifierKeys(event, false, true, false);
175
+
162
176
  const isPageDownShift = event => (event.key ? event.key === "PageDown" : event.keyCode === KeyCodes.PAGE_DOWN) && checkModifierKeys(event, false, false, true);
163
177
 
178
+ const isPageDownAlt = event => (event.key ? event.key === "PageDown" : event.keyCode === KeyCodes.PAGE_DOWN) && checkModifierKeys(event, false, true, false);
179
+
164
180
  const isPageUpShiftCtrl = event => (event.key ? event.key === "PageUp" : event.keyCode === KeyCodes.PAGE_UP) && checkModifierKeys(event, true, false, true);
165
181
 
166
182
  const isPageDownShiftCtrl = event => (event.key ? event.key === "PageDown" : event.keyCode === KeyCodes.PAGE_DOWN) && checkModifierKeys(event, true, false, true);
@@ -183,10 +199,20 @@ const isF4 = event => {
183
199
 
184
200
  const isF4Shift = event => (event.key ? event.key === "F4" : event.keyCode === KeyCodes.F4) && checkModifierKeys(event, false, false, true);
185
201
 
202
+ const isF6Next = event => ((event.key ? event.key === "F6" : event.keyCode === KeyCodes.F6) && checkModifierKeys(event, false, false, false))
203
+ || ((event.key ? (event.key === "ArrowDown" || event.key === "Down") : event.keyCode === KeyCodes.ARROW_DOWN) && checkModifierKeys(event, true, true, false));
204
+
205
+ const isF6Previous = event => ((event.key ? event.key === "F6" : event.keyCode === KeyCodes.F6) && checkModifierKeys(event, false, false, true))
206
+ || ((event.key ? (event.key === "ArrowUp" || event.key === "Up") : event.keyCode === KeyCodes.ARROW_Up) && checkModifierKeys(event, true, true, false));
207
+
208
+ const isF7 = event => (event.key ? event.key === "F7" : event.keyCode === KeyCodes.F7) && !hasModifierKeys(event);
209
+
186
210
  const isShowByArrows = event => {
187
211
  return ((event.key === "ArrowDown" || event.key === "Down") || (event.key === "ArrowUp" || event.key === "Up")) && checkModifierKeys(event, /* Ctrl */ false, /* Alt */ true, /* Shift */ false);
188
212
  };
189
213
 
214
+ const isShift = event => event.key === "Shift" || event.keyCode === KeyCodes.SHIFT;
215
+
190
216
  const hasModifierKeys = event => event.shiftKey || event.altKey || getCtrlKey(event);
191
217
 
192
218
  const getCtrlKey = event => !!(event.metaKey || event.ctrlKey); // double negation doesn't have effect on boolean but ensures null and undefined are equivalent to false.
@@ -208,6 +234,12 @@ export {
208
234
  isDownCtrl,
209
235
  isUpShift,
210
236
  isDownShift,
237
+ isUpAlt,
238
+ isDownAlt,
239
+ isLeftShift,
240
+ isRightShift,
241
+ isLeftShiftCtrl,
242
+ isRightShiftCtrl,
211
243
  isUpShiftCtrl,
212
244
  isDownShiftCtrl,
213
245
  isHome,
@@ -224,10 +256,16 @@ export {
224
256
  isShow,
225
257
  isF4,
226
258
  isF4Shift,
259
+ isF6Previous,
260
+ isF6Next,
261
+ isF7,
227
262
  isPageUp,
228
263
  isPageDown,
229
264
  isPageUpShift,
265
+ isPageUpAlt,
230
266
  isPageDownShift,
267
+ isPageDownAlt,
231
268
  isPageUpShiftCtrl,
232
269
  isPageDownShiftCtrl,
270
+ isShift,
233
271
  };
@@ -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
  });
@@ -0,0 +1,107 @@
1
+ import VersionInfo from "./generated/VersionInfo.js";
2
+ import getSharedResource from "./getSharedResource.js";
3
+
4
+ let currentRuntimeIndex;
5
+ let currentRuntimeAlias = "";
6
+
7
+ const compareCache = new Map();
8
+
9
+ /**
10
+ * Central registry where all runtimes register themselves by pushing an object.
11
+ * The index in the registry servers as an ID for the runtime.
12
+ * @type {*}
13
+ */
14
+ const Runtimes = getSharedResource("Runtimes", []);
15
+
16
+ /**
17
+ * Registers the current runtime in the shared runtimes resource registry
18
+ */
19
+ const registerCurrentRuntime = () => {
20
+ if (currentRuntimeIndex === undefined) {
21
+ currentRuntimeIndex = Runtimes.length;
22
+ Runtimes.push({
23
+ ...VersionInfo,
24
+ alias: currentRuntimeAlias,
25
+ description: `Runtime ${currentRuntimeIndex} - ver ${VersionInfo.version}${currentRuntimeAlias ? ` (${currentRuntimeAlias})` : ""}`,
26
+ });
27
+ }
28
+ };
29
+
30
+ /**
31
+ * Returns the index of the current runtime's object in the shared runtimes resource registry
32
+ * @returns {*}
33
+ */
34
+ const getCurrentRuntimeIndex = () => {
35
+ return currentRuntimeIndex;
36
+ };
37
+
38
+ /**
39
+ * Compares two runtimes and returns 1 if the first is of a bigger version, -1 if the second is of a bigger version, and 0 if equal
40
+ * @param index1 The index of the first runtime to compare
41
+ * @param index2 The index of the second runtime to compare
42
+ * @returns {number}
43
+ */
44
+ const compareRuntimes = (index1, index2) => {
45
+ const cacheIndex = `${index1},${index2}`;
46
+ if (compareCache.has(cacheIndex)) {
47
+ return compareCache.get(cacheIndex);
48
+ }
49
+
50
+ const runtime1 = Runtimes[index1];
51
+ const runtime2 = Runtimes[index2];
52
+
53
+ if (!runtime1 || !runtime2) {
54
+ throw new Error("Invalid runtime index supplied");
55
+ }
56
+
57
+ // If any of the two is a next version, bigger buildTime wins
58
+ if (runtime1.isNext || runtime2.isNext) {
59
+ return runtime1.buildTime - runtime2.buildTime;
60
+ }
61
+
62
+ // If major versions differ, bigger one wins
63
+ const majorDiff = runtime1.major - runtime2.major;
64
+ if (majorDiff) {
65
+ return majorDiff;
66
+ }
67
+
68
+ // If minor versions differ, bigger one wins
69
+ const minorDiff = runtime1.minor - runtime2.minor;
70
+ if (minorDiff) {
71
+ return minorDiff;
72
+ }
73
+
74
+ // If patch versions differ, bigger one wins
75
+ const patchDiff = runtime1.patch - runtime2.patch;
76
+ if (patchDiff) {
77
+ return patchDiff;
78
+ }
79
+
80
+ // Bigger suffix wins, f.e. rc10 > rc9
81
+ // Important: suffix is alphanumeric, must use natural compare
82
+ const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: "base" });
83
+ const result = collator.compare(runtime1.suffix, runtime2.suffix);
84
+
85
+ compareCache.set(cacheIndex, result);
86
+ return result;
87
+ };
88
+
89
+ /**
90
+ * Set an alias for the the current app/library/microfrontend which will appear in debug messages and console warnings
91
+ * @param alias
92
+ */
93
+ const setRuntimeAlias = alias => {
94
+ currentRuntimeAlias = alias;
95
+ };
96
+
97
+ const getAllRuntimes = () => {
98
+ return Runtimes;
99
+ };
100
+
101
+ export {
102
+ getCurrentRuntimeIndex,
103
+ registerCurrentRuntime,
104
+ compareRuntimes,
105
+ setRuntimeAlias,
106
+ getAllRuntimes,
107
+ };
@@ -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
  *
@@ -24,6 +25,9 @@ class StaticAreaItem extends HTMLElement {
24
25
  setOwnerElement(ownerElement) {
25
26
  this.ownerElement = ownerElement;
26
27
  this.classList.add(this.ownerElement._id); // used for getting the popover in the tests
28
+ if (this.ownerElement.hasAttribute("data-ui5-static-stable")) {
29
+ this.setAttribute("data-ui5-stable", this.ownerElement.getAttribute("data-ui5-static-stable")); // stable selector
30
+ }
27
31
  }
28
32
 
29
33
  /**
@@ -33,6 +37,7 @@ class StaticAreaItem extends HTMLElement {
33
37
  update() {
34
38
  if (this._rendered) {
35
39
  this._updateContentDensity();
40
+ this._updateDirection();
36
41
  updateShadowRoot(this.ownerElement, true);
37
42
  }
38
43
  }
@@ -51,6 +56,15 @@ class StaticAreaItem extends HTMLElement {
51
56
  }
52
57
  }
53
58
 
59
+ _updateDirection() {
60
+ const dir = getEffectiveDir(this.ownerElement);
61
+ if (dir) {
62
+ this.setAttribute("dir", dir);
63
+ } else {
64
+ this.removeAttribute("dir");
65
+ }
66
+ }
67
+
54
68
  /**
55
69
  * @protected
56
70
  * Returns reference to the DOM element where the current fragment is added.
@@ -65,15 +79,6 @@ class StaticAreaItem extends HTMLElement {
65
79
  return this.shadowRoot;
66
80
  }
67
81
 
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
82
  static getTag() {
78
83
  const pureTag = "ui5-static-area-item";
79
84
  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
  /**
@@ -101,8 +101,10 @@ class UI5Element extends HTMLElement {
101
101
  */
102
102
  async connectedCallback() {
103
103
  this.setAttribute(this.constructor.getMetadata().getPureTag(), "");
104
+ if (this.constructor.getMetadata().supportsF6FastNavigation()) {
105
+ this.setAttribute("data-sap-ui-fastnavgroup", "true");
106
+ }
104
107
 
105
- const needsShadowDOM = this.constructor._needsShadowDOM();
106
108
  const slotsAreManaged = this.constructor.getMetadata().slotsAreManaged();
107
109
 
108
110
  this._inDOM = true;
@@ -113,10 +115,6 @@ class UI5Element extends HTMLElement {
113
115
  await this._processChildren();
114
116
  }
115
117
 
116
- if (needsShadowDOM && !this.shadowRoot) { // Workaround for Firefox74 bug
117
- await Promise.resolve();
118
- }
119
-
120
118
  if (!this._inDOM) { // Component removed from DOM while _processChildren was running
121
119
  return;
122
120
  }
@@ -134,7 +132,6 @@ class UI5Element extends HTMLElement {
134
132
  * @private
135
133
  */
136
134
  disconnectedCallback() {
137
- const needsShadowDOM = this.constructor._needsShadowDOM();
138
135
  const slotsAreManaged = this.constructor.getMetadata().slotsAreManaged();
139
136
 
140
137
  this._inDOM = false;
@@ -143,13 +140,11 @@ class UI5Element extends HTMLElement {
143
140
  this._stopObservingDOMChildren();
144
141
  }
145
142
 
146
- if (needsShadowDOM) {
147
- if (this._fullyConnected) {
148
- if (typeof this.onExitDOM === "function") {
149
- this.onExitDOM();
150
- }
151
- this._fullyConnected = false;
143
+ if (this._fullyConnected) {
144
+ if (typeof this.onExitDOM === "function") {
145
+ this.onExitDOM();
152
146
  }
147
+ this._fullyConnected = false;
153
148
  }
154
149
 
155
150
  if (this.staticAreaItem && this.staticAreaItem.parentElement) {
@@ -259,7 +254,8 @@ class UI5Element extends HTMLElement {
259
254
 
260
255
  // Listen for any invalidation on the child if invalidateOnChildChange is true or an object (ignore when false or not set)
261
256
  if (child.isUI5Element && slotData.invalidateOnChildChange) {
262
- child._attachChange(this._getChildChangeListener(slotName));
257
+ const method = (child.attachInvalidate || child._attachChange).bind(child);
258
+ method(this._getChildChangeListener(slotName));
263
259
  }
264
260
 
265
261
  // Listen for the slotchange event if the child is a slot itself
@@ -319,7 +315,8 @@ class UI5Element extends HTMLElement {
319
315
 
320
316
  children.forEach(child => {
321
317
  if (child && child.isUI5Element) {
322
- child._detachChange(this._getChildChangeListener(slotName));
318
+ const method = (child.detachInvalidate || child._detachChange).bind(child);
319
+ method(this._getChildChangeListener(slotName));
323
320
  }
324
321
 
325
322
  if (isSlot(child)) {
@@ -334,20 +331,20 @@ class UI5Element extends HTMLElement {
334
331
  * Attach a callback that will be executed whenever the component is invalidated
335
332
  *
336
333
  * @param callback
337
- * @protected
334
+ * @public
338
335
  */
339
- _attachChange(callback) {
340
- this._eventProvider.attachEvent("change", callback);
336
+ attachInvalidate(callback) {
337
+ this._eventProvider.attachEvent("invalidate", callback);
341
338
  }
342
339
 
343
340
  /**
344
341
  * Detach the callback that is executed whenever the component is invalidated
345
342
  *
346
343
  * @param callback
347
- * @protected
344
+ * @public
348
345
  */
349
- _detachChange(callback) {
350
- this._eventProvider.detachEvent("change", callback);
346
+ detachInvalidate(callback) {
347
+ this._eventProvider.detachEvent("invalidate", callback);
351
348
  }
352
349
 
353
350
  /**
@@ -384,12 +381,8 @@ class UI5Element extends HTMLElement {
384
381
  const propertyTypeClass = properties[nameInCamelCase].type;
385
382
  if (propertyTypeClass === Boolean) {
386
383
  newValue = newValue !== null;
387
- }
388
- if (propertyTypeClass === Integer) {
389
- newValue = parseInt(newValue);
390
- }
391
- if (propertyTypeClass === Float) {
392
- newValue = parseFloat(newValue);
384
+ } else if (isDescendantOf(propertyTypeClass, DataType)) {
385
+ newValue = propertyTypeClass.attributeToProperty(newValue);
393
386
  }
394
387
  this[nameInCamelCase] = newValue;
395
388
  }
@@ -402,22 +395,24 @@ class UI5Element extends HTMLElement {
402
395
  if (!this.constructor.getMetadata().hasAttribute(name)) {
403
396
  return;
404
397
  }
405
-
406
- if (typeof newValue === "object") {
407
- return;
408
- }
409
-
398
+ const properties = this.constructor.getMetadata().getProperties();
399
+ const propertyTypeClass = properties[name].type;
410
400
  const attrName = camelToKebabCase(name);
411
401
  const attrValue = this.getAttribute(attrName);
412
- if (typeof newValue === "boolean") {
402
+
403
+ if (propertyTypeClass === Boolean) {
413
404
  if (newValue === true && attrValue === null) {
414
405
  this.setAttribute(attrName, "");
415
406
  } else if (newValue === false && attrValue !== null) {
416
407
  this.removeAttribute(attrName);
417
408
  }
418
- } else if (attrValue !== newValue) {
419
- this.setAttribute(attrName, newValue);
420
- }
409
+ } else if (isDescendantOf(propertyTypeClass, DataType)) {
410
+ this.setAttribute(attrName, propertyTypeClass.propertyToAttribute(newValue));
411
+ } else if (typeof newValue !== "object") {
412
+ if (attrValue !== newValue) {
413
+ this.setAttribute(attrName, newValue);
414
+ }
415
+ } // else { return; } // old object handling
421
416
  }
422
417
 
423
418
  /**
@@ -617,25 +612,27 @@ class UI5Element extends HTMLElement {
617
612
 
618
613
  /**
619
614
  * Returns the DOM Element inside the Shadow Root that corresponds to the opening tag in the UI5 Web Component's template
615
+ * *Note:* For logical (abstract) elements (items, options, etc...), returns the part of the parent's DOM that represents this option
620
616
  * Use this method instead of "this.shadowRoot" to read the Shadow DOM, if ever necessary
617
+ *
621
618
  * @public
622
619
  */
623
620
  getDomRef() {
621
+ // If a component set _getRealDomRef to its children, use the return value of this function
622
+ if (typeof this._getRealDomRef === "function") {
623
+ return this._getRealDomRef();
624
+ }
625
+
624
626
  if (!this.shadowRoot || this.shadowRoot.children.length === 0) {
625
627
  return;
626
628
  }
627
629
 
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) {
630
+ const children = [...this.shadowRoot.children].filter(child => !["link", "style"].includes(child.localName));
631
+ if (children.length !== 1) {
637
632
  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
633
  }
634
+
635
+ return children[0];
639
636
  }
640
637
 
641
638
  /**
@@ -661,17 +658,6 @@ class UI5Element extends HTMLElement {
661
658
  return this.getFocusDomRef();
662
659
  }
663
660
 
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
661
  /**
676
662
  * Set the focus to the element, returned by "getFocusDomRef()" (marked by "data-sap-focus-ref")
677
663
  * @public
@@ -861,6 +847,8 @@ class UI5Element extends HTMLElement {
861
847
  const oldState = this._state[prop];
862
848
  if (propData.multiple && propData.compareValues) {
863
849
  isDifferent = !arraysAreEqual(oldState, value);
850
+ } else if (isDescendantOf(propData.type, DataType)) {
851
+ isDifferent = !propData.type.valuesAreEqual(oldState, value);
864
852
  } else {
865
853
  isDifferent = oldState !== value;
866
854
  }
@@ -996,6 +984,7 @@ class UI5Element extends HTMLElement {
996
984
  this._generateAccessors();
997
985
  registerTag(tag);
998
986
  window.customElements.define(tag, this);
987
+ preloadLinks(this);
999
988
 
1000
989
  if (altTag && !customElements.get(altTag)) {
1001
990
  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
  /**
@@ -188,6 +188,14 @@ class UI5ElementMetadata {
188
188
  return !!this.metadata.managedSlots;
189
189
  }
190
190
 
191
+ /**
192
+ * Determines whether this control supports F6 fast navigation
193
+ * @public
194
+ */
195
+ supportsF6FastNavigation() {
196
+ return !!this.metadata.fastNavigation;
197
+ }
198
+
191
199
  /**
192
200
  * Returns an object with key-value pairs of properties and their metadata definitions
193
201
  * @public
@@ -212,6 +220,14 @@ class UI5ElementMetadata {
212
220
  return !!this.metadata.languageAware;
213
221
  }
214
222
 
223
+ /**
224
+ * Determines whether this UI5 Element has any theme dependant carachteristics.
225
+ * @returns {boolean}
226
+ */
227
+ isThemeAware() {
228
+ return !!this.metadata.themeAware;
229
+ }
230
+
215
231
  /**
216
232
  * Matches a changed entity (property/slot) with the given name against the "invalidateOnChildChange" configuration
217
233
  * and determines whether this should cause and invalidation