@ui5/webcomponents-base 0.0.0-aeb93167c → 0.0.0-b053ad005

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 (305) hide show
  1. package/.eslintignore +3 -0
  2. package/CHANGELOG.md +84 -0
  3. package/README.md +26 -2
  4. package/bundle.esm.js +13 -11
  5. package/dist/AssetRegistry.js +8 -9
  6. package/dist/Boot.js +43 -0
  7. package/dist/CSP.js +59 -0
  8. package/dist/DOMObserver.js +65 -0
  9. package/dist/Device.js +62 -778
  10. package/dist/EventProvider.js +30 -26
  11. package/dist/FontFace.js +7 -95
  12. package/dist/InitialConfiguration.js +37 -21
  13. package/dist/Keys.js +51 -0
  14. package/dist/ManagedStyles.js +83 -0
  15. package/dist/MediaRange.js +109 -0
  16. package/{src/util/parseProperties.js → dist/PropertiesFileFormat.js} +6 -0
  17. package/dist/Render.js +175 -0
  18. package/dist/RenderScheduler.js +16 -138
  19. package/dist/StaticArea.js +1 -29
  20. package/dist/StaticAreaItem.js +56 -66
  21. package/dist/SystemCSSVars.js +4 -25
  22. package/dist/UI5Element.js +301 -383
  23. package/dist/UI5ElementMetadata.js +123 -16
  24. package/dist/asset-registries/Icons.js +121 -14
  25. package/dist/asset-registries/Illustrations.js +30 -0
  26. package/dist/asset-registries/LocaleData.js +91 -67
  27. package/dist/asset-registries/Themes.js +23 -33
  28. package/dist/asset-registries/i18n.js +61 -50
  29. package/dist/assets-meta/IconCollectionsAlias.js +18 -0
  30. package/dist/config/Language.js +18 -20
  31. package/dist/config/Theme.js +14 -0
  32. package/dist/css/FontFace.css +45 -0
  33. package/dist/css/OverrideFontFace.css +32 -0
  34. package/dist/css/SystemCSSVars.css +17 -0
  35. package/dist/delegate/ItemNavigation.js +233 -201
  36. package/dist/delegate/ResizeHandler.js +78 -37
  37. package/dist/delegate/ScrollEnablement.js +49 -20
  38. package/dist/features/OpenUI5Support.js +41 -6
  39. package/dist/generated/AssetParameters.js +1 -1
  40. package/dist/generated/css/FontFace.css.js +5 -0
  41. package/dist/generated/css/OverrideFontFace.css.js +5 -0
  42. package/dist/generated/css/SystemCSSVars.css.js +5 -0
  43. package/dist/i18nBundle.js +38 -4
  44. package/dist/isLegacyBrowser.js +3 -0
  45. package/dist/locale/applyDirection.js +6 -4
  46. package/dist/locale/directionChange.js +32 -0
  47. package/dist/locale/getEffectiveDir.js +28 -0
  48. package/dist/locale/languageChange.js +1 -1
  49. package/dist/renderer/LitRenderer.js +24 -21
  50. package/dist/renderer/directives/style-map.js +72 -0
  51. package/dist/resources/bundle.esm.js +17 -109
  52. package/dist/resources/bundle.esm.js.map +1 -1
  53. package/dist/sap/base/Log.js +241 -0
  54. package/dist/sap/base/assert.js +8 -0
  55. package/dist/sap/base/security/URLListValidator.js +148 -0
  56. package/dist/sap/base/security/sanitizeHTML.js +16 -0
  57. package/dist/sap/base/util/now.js +7 -0
  58. package/dist/sap/ui/thirdparty/caja-html-sanitizer.js +3585 -0
  59. package/dist/test-resources/assets/Themes.js +8 -8
  60. package/dist/test-resources/elements/Parent.js +6 -2
  61. package/dist/test-resources/elements/WithStaticArea.js +2 -1
  62. package/dist/test-resources/pages/AllTestElements.html +3 -3
  63. package/dist/test-resources/pages/Configuration.html +0 -2
  64. package/dist/test-resources/pages/ConfigurationScript.html +0 -2
  65. package/dist/test-resources/pages/i18n.html +2 -9
  66. package/dist/test-resources/specs/ConfigurationChange.spec.js +10 -8
  67. package/dist/test-resources/specs/ConfigurationScript.spec.js +25 -23
  68. package/dist/test-resources/specs/ConfigurationURL.spec.js +65 -17
  69. package/dist/test-resources/specs/CustomTheme.spec.js +9 -7
  70. package/dist/test-resources/specs/EventProvider.spec.js +63 -0
  71. package/dist/test-resources/specs/StaticArea.spec.js +56 -12
  72. package/dist/test-resources/specs/Theming.spec.js +12 -10
  73. package/dist/test-resources/specs/UI5ElementInvalidation.js +54 -70
  74. package/dist/test-resources/specs/UI5ElementLifecycle.js +17 -15
  75. package/dist/test-resources/specs/UI5ElementListenForChildPropChanges.spec.js +25 -51
  76. package/dist/test-resources/specs/UI5ElementMetadataExt.js +9 -7
  77. package/dist/test-resources/specs/UI5ElementPropertyValidation.js +7 -5
  78. package/dist/test-resources/specs/UI5ElementPropsAndAttrs.spec.js +37 -35
  79. package/dist/test-resources/specs/UI5ElementShadowDOM.js +10 -8
  80. package/dist/test-resources/specs/UI5ElementSlots.js +10 -8
  81. package/dist/theming/CustomStyle.js +2 -2
  82. package/dist/theming/applyTheme.js +5 -14
  83. package/dist/theming/getConstructableStyle.js +7 -6
  84. package/dist/theming/getEffectiveLinksHrefs.js +20 -0
  85. package/dist/theming/getEffectiveStyle.js +15 -8
  86. package/dist/theming/getStylesString.js +4 -2
  87. package/dist/theming/getThemeDesignerTheme.js +2 -1
  88. package/dist/theming/preloadLinks.js +23 -0
  89. package/dist/types/CSSColor.js +9 -0
  90. package/dist/types/CalendarType.js +1 -1
  91. package/dist/types/DataType.js +13 -1
  92. package/dist/types/Float.js +4 -0
  93. package/dist/types/Integer.js +4 -0
  94. package/dist/types/InvisibleMessageMode.js +30 -0
  95. package/dist/types/ItemNavigationBehavior.js +2 -7
  96. package/dist/types/PopupState.js +1 -1
  97. package/dist/types/ValueState.js +1 -1
  98. package/dist/updateShadowRoot.js +30 -0
  99. package/dist/util/AriaLabelHelper.js +4 -4
  100. package/dist/util/Caret.js +45 -0
  101. package/dist/util/ColorConversion.js +370 -0
  102. package/dist/util/FocusableElements.js +17 -6
  103. package/dist/util/HTMLSanitizer.js +7 -0
  104. package/dist/util/InvisibleMessage.js +58 -0
  105. package/dist/util/PopupUtils.js +93 -0
  106. package/dist/util/SlotsHelper.js +43 -0
  107. package/dist/util/TabbableElements.js +1 -1
  108. package/dist/util/arraysAreEqual.js +15 -0
  109. package/dist/util/clamp.js +12 -0
  110. package/dist/util/createLinkInHead.js +19 -0
  111. package/dist/util/debounce.js +17 -0
  112. package/dist/util/getActiveElement.js +11 -0
  113. package/dist/util/getClassCopy.js +10 -0
  114. package/dist/util/getEffectiveContentDensity.js +5 -0
  115. package/dist/util/isElementInView.js +15 -0
  116. package/dist/util/isNodeTabbable.js +4 -4
  117. package/hash.txt +1 -0
  118. package/index.js +1 -1
  119. package/lib/generate-asset-parameters/index.js +0 -1
  120. package/lib/generate-styles/index.js +18 -0
  121. package/package-scripts.js +37 -19
  122. package/package.json +19 -13
  123. package/src/AssetRegistry.js +8 -9
  124. package/src/Boot.js +43 -0
  125. package/src/CSP.js +59 -0
  126. package/src/DOMObserver.js +65 -0
  127. package/src/Device.js +62 -778
  128. package/src/EventProvider.js +30 -26
  129. package/src/FontFace.js +7 -95
  130. package/src/InitialConfiguration.js +37 -21
  131. package/src/Keys.js +51 -0
  132. package/src/ManagedStyles.js +83 -0
  133. package/src/MediaRange.js +109 -0
  134. package/{dist/util/parseProperties.js → src/PropertiesFileFormat.js} +6 -0
  135. package/src/Render.js +175 -0
  136. package/src/RenderScheduler.js +16 -138
  137. package/src/StaticArea.js +1 -29
  138. package/src/StaticAreaItem.js +56 -66
  139. package/src/SystemCSSVars.js +4 -25
  140. package/src/UI5Element.js +301 -383
  141. package/src/UI5ElementMetadata.js +123 -16
  142. package/src/asset-registries/Icons.js +121 -14
  143. package/src/asset-registries/Illustrations.js +30 -0
  144. package/src/asset-registries/LocaleData.js +91 -67
  145. package/src/asset-registries/Themes.js +23 -33
  146. package/src/asset-registries/i18n.js +61 -50
  147. package/src/assets-meta/IconCollectionsAlias.js +18 -0
  148. package/src/config/Language.js +18 -20
  149. package/src/config/Theme.js +14 -0
  150. package/src/css/FontFace.css +45 -0
  151. package/src/css/OverrideFontFace.css +32 -0
  152. package/src/css/SystemCSSVars.css +17 -0
  153. package/src/delegate/ItemNavigation.js +233 -201
  154. package/src/delegate/ResizeHandler.js +78 -37
  155. package/src/delegate/ScrollEnablement.js +49 -20
  156. package/src/features/OpenUI5Support.js +41 -6
  157. package/src/i18nBundle.js +38 -4
  158. package/src/isLegacyBrowser.js +3 -0
  159. package/src/locale/applyDirection.js +6 -4
  160. package/src/locale/directionChange.js +32 -0
  161. package/src/locale/getEffectiveDir.js +28 -0
  162. package/src/locale/languageChange.js +1 -1
  163. package/src/renderer/LitRenderer.js +24 -21
  164. package/src/renderer/directives/style-map.js +72 -0
  165. package/src/theming/CustomStyle.js +2 -2
  166. package/src/theming/applyTheme.js +5 -14
  167. package/src/theming/getConstructableStyle.js +7 -6
  168. package/src/theming/getEffectiveLinksHrefs.js +20 -0
  169. package/src/theming/getEffectiveStyle.js +15 -8
  170. package/src/theming/getStylesString.js +4 -2
  171. package/src/theming/getThemeDesignerTheme.js +2 -1
  172. package/src/theming/preloadLinks.js +23 -0
  173. package/src/types/CSSColor.js +9 -0
  174. package/src/types/CalendarType.js +1 -1
  175. package/src/types/DataType.js +13 -1
  176. package/src/types/Float.js +4 -0
  177. package/src/types/Integer.js +4 -0
  178. package/src/types/InvisibleMessageMode.js +30 -0
  179. package/src/types/ItemNavigationBehavior.js +2 -7
  180. package/src/types/PopupState.js +1 -1
  181. package/src/types/ValueState.js +1 -1
  182. package/src/updateShadowRoot.js +30 -0
  183. package/src/util/AriaLabelHelper.js +4 -4
  184. package/src/util/Caret.js +45 -0
  185. package/src/util/ColorConversion.js +370 -0
  186. package/src/util/FocusableElements.js +17 -6
  187. package/src/util/HTMLSanitizer.js +7 -0
  188. package/src/util/InvisibleMessage.js +58 -0
  189. package/src/util/PopupUtils.js +93 -0
  190. package/src/util/SlotsHelper.js +43 -0
  191. package/src/util/TabbableElements.js +1 -1
  192. package/src/util/arraysAreEqual.js +15 -0
  193. package/src/util/clamp.js +12 -0
  194. package/src/util/createLinkInHead.js +19 -0
  195. package/src/util/debounce.js +17 -0
  196. package/src/util/getActiveElement.js +11 -0
  197. package/src/util/getClassCopy.js +10 -0
  198. package/src/util/getEffectiveContentDensity.js +5 -0
  199. package/src/util/isElementInView.js +15 -0
  200. package/src/util/isNodeTabbable.js +4 -4
  201. package/used-modules.txt +7 -0
  202. package/bundle.es5.js +0 -28
  203. package/dist/SVGIconRegistry.js +0 -73
  204. package/dist/boot.js +0 -34
  205. package/dist/compatibility/DOMObserver.js +0 -62
  206. package/dist/compatibility/patchNodeValue.js +0 -24
  207. package/dist/compatibility/whenPolyfillLoaded.js +0 -26
  208. package/dist/config/AssetsPath.js +0 -17
  209. package/dist/delegate/CustomResize.js +0 -78
  210. package/dist/delegate/NativeResize.js +0 -45
  211. package/dist/features/PropertiesFormatSupport.js +0 -8
  212. package/dist/features/browsersupport/Edge.js +0 -6
  213. package/dist/features/browsersupport/IE11.js +0 -42
  214. package/dist/features/browsersupport/IE11WithWebComponentsPolyfill.js +0 -5
  215. package/dist/renderer/ifDefined.js +0 -21
  216. package/dist/renderer/scopeHTML.js +0 -32
  217. package/dist/resources/bundle.es5.js +0 -212
  218. package/dist/resources/bundle.es5.js.map +0 -1
  219. package/dist/theming/CSSVarsPonyfill.js +0 -68
  220. package/dist/theming/adaptCSSForIE.js +0 -95
  221. package/dist/theming/createComponentStyleTag.js +0 -54
  222. package/dist/theming/createThemePropertiesStyleTag.js +0 -20
  223. package/dist/thirdparty/Array.from.js +0 -16
  224. package/dist/thirdparty/Array.prototype.fill.js +0 -44
  225. package/dist/thirdparty/Array.prototype.find.js +0 -46
  226. package/dist/thirdparty/Array.prototype.includes.js +0 -51
  227. package/dist/thirdparty/Element.prototype.closest.js +0 -11
  228. package/dist/thirdparty/Element.prototype.matches.js +0 -6
  229. package/dist/thirdparty/Map.prototype.keys.js +0 -9
  230. package/dist/thirdparty/Number.isInteger.js +0 -5
  231. package/dist/thirdparty/Number.isNaN.js +0 -1
  232. package/dist/thirdparty/Number.parseFloat.js +0 -1
  233. package/dist/thirdparty/Number.parseInt.js +0 -1
  234. package/dist/thirdparty/Object.assign.js +0 -31
  235. package/dist/thirdparty/Object.entries.js +0 -11
  236. package/dist/thirdparty/Symbol.js +0 -2
  237. package/dist/thirdparty/WeakSet.js +0 -27
  238. package/dist/thirdparty/es6-string-methods.js +0 -182
  239. package/dist/thirdparty/events-polyfills.js +0 -89
  240. package/dist/thirdparty/fetch.js +0 -1
  241. package/dist/thirdparty/template.js +0 -600
  242. package/dist/thirdparty/webcomponents-sd-ce-pf.js +0 -318
  243. package/dist/util/EffectiveAssetPath.js +0 -27
  244. package/dist/util/isSlot.js +0 -3
  245. package/dist/webcomponentsjs/LICENSE.md +0 -19
  246. package/dist/webcomponentsjs/README.md +0 -229
  247. package/dist/webcomponentsjs/bundles/webcomponents-ce.js +0 -63
  248. package/dist/webcomponentsjs/bundles/webcomponents-ce.js.map +0 -1
  249. package/dist/webcomponentsjs/bundles/webcomponents-sd-ce-pf.js +0 -297
  250. package/dist/webcomponentsjs/bundles/webcomponents-sd-ce-pf.js.map +0 -1
  251. package/dist/webcomponentsjs/bundles/webcomponents-sd-ce.js +0 -208
  252. package/dist/webcomponentsjs/bundles/webcomponents-sd-ce.js.map +0 -1
  253. package/dist/webcomponentsjs/bundles/webcomponents-sd.js +0 -166
  254. package/dist/webcomponentsjs/bundles/webcomponents-sd.js.map +0 -1
  255. package/dist/webcomponentsjs/custom-elements-es5-adapter.js +0 -15
  256. package/dist/webcomponentsjs/package.json +0 -46
  257. package/dist/webcomponentsjs/src/entrypoints/custom-elements-es5-adapter-index.js +0 -16
  258. package/dist/webcomponentsjs/src/entrypoints/webcomponents-bundle-index.js +0 -53
  259. package/dist/webcomponentsjs/src/entrypoints/webcomponents-ce-index.js +0 -17
  260. package/dist/webcomponentsjs/src/entrypoints/webcomponents-sd-ce-index.js +0 -19
  261. package/dist/webcomponentsjs/src/entrypoints/webcomponents-sd-ce-pf-index.js +0 -28
  262. package/dist/webcomponentsjs/src/entrypoints/webcomponents-sd-index.js +0 -18
  263. package/dist/webcomponentsjs/webcomponents-bundle.js +0 -298
  264. package/dist/webcomponentsjs/webcomponents-bundle.js.map +0 -1
  265. package/dist/webcomponentsjs/webcomponents-loader.js +0 -185
  266. package/src/SVGIconRegistry.js +0 -73
  267. package/src/boot.js +0 -34
  268. package/src/compatibility/DOMObserver.js +0 -62
  269. package/src/compatibility/patchNodeValue.js +0 -24
  270. package/src/compatibility/whenPolyfillLoaded.js +0 -26
  271. package/src/config/AssetsPath.js +0 -17
  272. package/src/delegate/CustomResize.js +0 -78
  273. package/src/delegate/NativeResize.js +0 -45
  274. package/src/features/PropertiesFormatSupport.js +0 -8
  275. package/src/features/browsersupport/Edge.js +0 -6
  276. package/src/features/browsersupport/IE11.js +0 -42
  277. package/src/features/browsersupport/IE11WithWebComponentsPolyfill.js +0 -5
  278. package/src/renderer/ifDefined.js +0 -21
  279. package/src/renderer/scopeHTML.js +0 -32
  280. package/src/theming/CSSVarsPonyfill.js +0 -68
  281. package/src/theming/adaptCSSForIE.js +0 -95
  282. package/src/theming/createComponentStyleTag.js +0 -54
  283. package/src/theming/createThemePropertiesStyleTag.js +0 -20
  284. package/src/thirdparty/Array.from.js +0 -16
  285. package/src/thirdparty/Array.prototype.fill.js +0 -44
  286. package/src/thirdparty/Array.prototype.find.js +0 -46
  287. package/src/thirdparty/Array.prototype.includes.js +0 -51
  288. package/src/thirdparty/Element.prototype.closest.js +0 -11
  289. package/src/thirdparty/Element.prototype.matches.js +0 -6
  290. package/src/thirdparty/Map.prototype.keys.js +0 -9
  291. package/src/thirdparty/Number.isInteger.js +0 -5
  292. package/src/thirdparty/Number.isNaN.js +0 -1
  293. package/src/thirdparty/Number.parseFloat.js +0 -1
  294. package/src/thirdparty/Number.parseInt.js +0 -1
  295. package/src/thirdparty/Object.assign.js +0 -31
  296. package/src/thirdparty/Object.entries.js +0 -11
  297. package/src/thirdparty/Symbol.js +0 -2
  298. package/src/thirdparty/WeakSet.js +0 -27
  299. package/src/thirdparty/es6-string-methods.js +0 -182
  300. package/src/thirdparty/events-polyfills.js +0 -89
  301. package/src/thirdparty/fetch.js +0 -1
  302. package/src/thirdparty/template.js +0 -600
  303. package/src/thirdparty/webcomponents-sd-ce-pf.js +0 -318
  304. package/src/util/EffectiveAssetPath.js +0 -27
  305. package/src/util/isSlot.js +0 -3
@@ -1,7 +1,7 @@
1
1
  import DataType from "./types/DataType.js";
2
2
  import isDescendantOf from "./util/isDescendantOf.js";
3
3
  import { camelToKebabCase } from "./util/StringHelper.js";
4
- import isSlot from "./util/isSlot.js";
4
+ import { getSlottedElements } from "./util/SlotsHelper.js";
5
5
  import { getEffectiveScopingSuffixForTag } from "./CustomElementsScope.js";
6
6
 
7
7
  /**
@@ -14,6 +14,50 @@ class UI5ElementMetadata {
14
14
  this.metadata = metadata;
15
15
  }
16
16
 
17
+ getInitialState() {
18
+ if (Object.prototype.hasOwnProperty.call(this, "_initialState")) {
19
+ return this._initialState;
20
+ }
21
+
22
+ const initialState = {};
23
+ const slotsAreManaged = this.slotsAreManaged();
24
+
25
+ // Initialize properties
26
+ const props = this.getProperties();
27
+ for (const propName in props) { // eslint-disable-line
28
+ const propType = props[propName].type;
29
+ const propDefaultValue = props[propName].defaultValue;
30
+
31
+ if (propType === Boolean) {
32
+ initialState[propName] = false;
33
+
34
+ if (propDefaultValue !== undefined) {
35
+ console.warn("The 'defaultValue' metadata key is ignored for all booleans properties, they would be initialized with 'false' by default"); // eslint-disable-line
36
+ }
37
+ } else if (props[propName].multiple) {
38
+ initialState[propName] = [];
39
+ } else if (propType === Object) {
40
+ initialState[propName] = "defaultValue" in props[propName] ? props[propName].defaultValue : {};
41
+ } else if (propType === String) {
42
+ initialState[propName] = "defaultValue" in props[propName] ? props[propName].defaultValue : "";
43
+ } else {
44
+ initialState[propName] = propDefaultValue;
45
+ }
46
+ }
47
+
48
+ // Initialize slots
49
+ if (slotsAreManaged) {
50
+ const slots = this.getSlots();
51
+ for (const [slotName, slotData] of Object.entries(slots)) { // eslint-disable-line
52
+ const propertyName = slotData.propertyName || slotName;
53
+ initialState[propertyName] = [];
54
+ }
55
+ }
56
+
57
+ this._initialState = initialState;
58
+ return initialState;
59
+ }
60
+
17
61
  /**
18
62
  * Only intended for use by UI5Element.js
19
63
  * @protected
@@ -82,7 +126,7 @@ class UI5ElementMetadata {
82
126
  */
83
127
  hasAttribute(propName) {
84
128
  const propData = this.getProperties()[propName];
85
- return propData.type !== Object && !propData.noAttribute;
129
+ return propData.type !== Object && !propData.noAttribute && !propData.multiple;
86
130
  }
87
131
 
88
132
  /**
@@ -167,6 +211,82 @@ class UI5ElementMetadata {
167
211
  isLanguageAware() {
168
212
  return !!this.metadata.languageAware;
169
213
  }
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
+
223
+ /**
224
+ * Matches a changed entity (property/slot) with the given name against the "invalidateOnChildChange" configuration
225
+ * and determines whether this should cause and invalidation
226
+ *
227
+ * @param slotName the name of the slot in which a child was changed
228
+ * @param type the type of change in the child: "property" or "slot"
229
+ * @param name the name of the property/slot that changed
230
+ * @returns {boolean}
231
+ */
232
+ shouldInvalidateOnChildChange(slotName, type, name) {
233
+ const config = this.getSlots()[slotName].invalidateOnChildChange;
234
+
235
+ // invalidateOnChildChange was not set in the slot metadata - by default child changes do not affect the component
236
+ if (config === undefined) {
237
+ return false;
238
+ }
239
+
240
+ // The simple format was used: invalidateOnChildChange: true/false;
241
+ if (typeof config === "boolean") {
242
+ return config;
243
+ }
244
+
245
+ // The complex format was used: invalidateOnChildChange: { properties, slots }
246
+ if (typeof config === "object") {
247
+ // A property was changed
248
+ if (type === "property") {
249
+ // The config object does not have a properties field
250
+ if (config.properties === undefined) {
251
+ return false;
252
+ }
253
+
254
+ // The config object has the short format: properties: true/false
255
+ if (typeof config.properties === "boolean") {
256
+ return config.properties;
257
+ }
258
+
259
+ // The config object has the complex format: properties: [...]
260
+ if (Array.isArray(config.properties)) {
261
+ return config.properties.includes(name);
262
+ }
263
+
264
+ throw new Error("Wrong format for invalidateOnChildChange.properties: boolean or array is expected");
265
+ }
266
+
267
+ // A slot was changed
268
+ if (type === "slot") {
269
+ // The config object does not have a slots field
270
+ if (config.slots === undefined) {
271
+ return false;
272
+ }
273
+
274
+ // The config object has the short format: slots: true/false
275
+ if (typeof config.slots === "boolean") {
276
+ return config.slots;
277
+ }
278
+
279
+ // The config object has the complex format: slots: [...]
280
+ if (Array.isArray(config.slots)) {
281
+ return config.slots.includes(name);
282
+ }
283
+
284
+ throw new Error("Wrong format for invalidateOnChildChange.slots: boolean or array is expected");
285
+ }
286
+ }
287
+
288
+ throw new Error("Wrong format for invalidateOnChildChange: boolean or object is expected");
289
+ }
170
290
  }
171
291
 
172
292
  const validateSingleProperty = (value, propData) => {
@@ -187,20 +307,7 @@ const validateSingleProperty = (value, propData) => {
187
307
  };
188
308
 
189
309
  const validateSingleSlot = (value, slotData) => {
190
- if (value === null) {
191
- return value;
192
- }
193
-
194
- const getSlottedNodes = el => {
195
- if (isSlot(el)) {
196
- return el.assignedNodes({ flatten: true }).filter(item => item instanceof HTMLElement);
197
- }
198
-
199
- return [el];
200
- };
201
-
202
- const slottedNodes = getSlottedNodes(value);
203
- slottedNodes.forEach(el => {
310
+ value && getSlottedElements(value).forEach(el => {
204
311
  if (!(el instanceof slotData.type)) {
205
312
  throw new Error(`${el} is not of type ${slotData.type}`);
206
313
  }
@@ -1,22 +1,37 @@
1
- import { registerIcon, registerCollectionPromise } from "../SVGIconRegistry.js";
2
- import { fetchJsonOnce } from "../util/FetchHelper.js";
3
- import { getEffectiveAssetPath } from "../util/EffectiveAssetPath.js";
1
+ import getSharedResource from "../getSharedResource.js";
2
+ import IconCollectionsAlias from "../assets-meta/IconCollectionsAlias.js";
3
+ import { isTheme } from "../config/Theme.js";
4
4
 
5
+ const loaders = new Map();
6
+ const registry = getSharedResource("SVGIcons.registry", new Map());
7
+ const iconCollectionPromises = getSharedResource("SVGIcons.promises", new Map());
8
+
9
+ const ICON_NOT_FOUND = "ICON_NOT_FOUND";
10
+
11
+ /**
12
+ * @deprecated
13
+ */
5
14
  const registerIconBundle = async (collectionName, bundleData) => {
6
- let resolveFn;
7
- const collectionFetched = new Promise(resolve => {
8
- resolveFn = resolve;
9
- });
10
- registerCollectionPromise(collectionName, collectionFetched);
15
+ throw new Error("This method has been removed. Use `registerIconLoader` instead.");
16
+ };
17
+
18
+ const registerIconLoader = async (collectionName, loader) => {
19
+ loaders.set(collectionName, loader);
20
+ };
11
21
 
12
- if (typeof bundleData !== "object") { // not inlined from build -> fetch it
13
- bundleData = await fetchJsonOnce(getEffectiveAssetPath(bundleData));
22
+ const _loadIconCollectionOnce = async collectionName => {
23
+ if (!iconCollectionPromises.has(collectionName)) {
24
+ if (!loaders.has(collectionName)) {
25
+ throw new Error(`No loader registered for the ${collectionName} icons collection. Probably you forgot to import the "AllIcons.js" module for the respective package.`);
26
+ }
27
+ const loadIcons = loaders.get(collectionName);
28
+ iconCollectionPromises.set(collectionName, loadIcons(collectionName));
14
29
  }
15
- fillRegistry(bundleData);
16
- resolveFn();
30
+
31
+ return iconCollectionPromises.get(collectionName);
17
32
  };
18
33
 
19
- const fillRegistry = bundleData => {
34
+ const _fillRegistry = bundleData => {
20
35
  Object.keys(bundleData.data).forEach(iconName => {
21
36
  const iconData = bundleData.data[iconName];
22
37
 
@@ -25,8 +40,100 @@ const fillRegistry = bundleData => {
25
40
  ltr: iconData.ltr,
26
41
  accData: iconData.acc,
27
42
  collection: bundleData.collection,
43
+ packageName: bundleData.packageName,
28
44
  });
29
45
  });
30
46
  };
31
47
 
32
- export { registerIconBundle }; // eslint-disable-line
48
+ // set
49
+ const registerIcon = (name, { pathData, ltr, accData, collection, packageName } = {}) => { // eslint-disable-line
50
+ if (!collection) {
51
+ collection = _getDefaultCollection();
52
+ }
53
+
54
+ const key = `${collection}/${name}`;
55
+ registry.set(key, {
56
+ pathData,
57
+ ltr,
58
+ accData,
59
+ packageName,
60
+ });
61
+ };
62
+
63
+ const _parseName = name => {
64
+ // silently support ui5-compatible URIs
65
+ if (name.startsWith("sap-icon://")) {
66
+ name = name.replace("sap-icon://", "");
67
+ }
68
+
69
+ let collection;
70
+ [name, collection] = name.split("/").reverse();
71
+ collection = collection || _getDefaultCollection();
72
+
73
+ // Normalize collection name.
74
+ // - resolve `SAP-icons-TNT` to `tnt`.
75
+ // - resolve `BusinessSuiteInAppSymbols` to `business-suite`.
76
+ // - resolve `horizon` to `SAP-icons-v5`,
77
+ // Note: aliases can be made as a feature, if more collections need it or more aliases are needed.
78
+ collection = _normalizeCollection(collection);
79
+ name = name.replace("icon-", "");
80
+
81
+ const registryKey = `${collection}/${name}`;
82
+ return { name, collection, registryKey };
83
+ };
84
+
85
+ const getIconDataSync = nameProp => {
86
+ const { registryKey } = _parseName(nameProp);
87
+ return registry.get(registryKey);
88
+ };
89
+
90
+ const getIconData = async nameProp => {
91
+ const { collection, registryKey } = _parseName(nameProp);
92
+
93
+ let iconData = ICON_NOT_FOUND;
94
+ try {
95
+ iconData = await _loadIconCollectionOnce(collection);
96
+ } catch (e) {
97
+ console.error(e.message); /* eslint-disable-line */
98
+ }
99
+
100
+ if (iconData === ICON_NOT_FOUND) {
101
+ return iconData;
102
+ }
103
+
104
+ if (!registry.has(registryKey)) {
105
+ // not filled by another await. many getters will await on the same loader, but fill only once
106
+ _fillRegistry(iconData);
107
+ }
108
+ return registry.get(registryKey);
109
+ };
110
+
111
+ // test page usage only
112
+ const _getRegisteredNames = async () => {
113
+ // fetch one icon of each collection to trigger the bundle load
114
+ await getIconData("edit");
115
+ await getIconData("tnt/arrow");
116
+ await getIconData("business-suite/3d");
117
+ return Array.from(registry.keys());
118
+ };
119
+
120
+ const _getDefaultCollection = () => {
121
+ return isTheme("sap_horizon") ? "SAP-icons-v5" : "SAP-icons";
122
+ };
123
+
124
+ const _normalizeCollection = collectionName => {
125
+ if (IconCollectionsAlias[collectionName]) {
126
+ return IconCollectionsAlias[collectionName];
127
+ }
128
+
129
+ return collectionName;
130
+ };
131
+
132
+ export {
133
+ registerIconBundle,
134
+ registerIconLoader,
135
+ getIconData,
136
+ getIconDataSync,
137
+ registerIcon,
138
+ _getRegisteredNames,
139
+ };
@@ -0,0 +1,30 @@
1
+ import getSharedResource from "../getSharedResource.js";
2
+
3
+ const registry = getSharedResource("SVGIllustration.registry", new Map());
4
+ const ILLUSTRATION_NOT_FOUND = "ILLUSTRATION_NOT_FOUND";
5
+
6
+ const registerIllustration = (name, { dialogSvg, sceneSvg, spotSvg, set, title, subtitle } = {}) => { // eslint-disable-line
7
+ registry.set(`${set}/${name}`, {
8
+ dialogSvg,
9
+ sceneSvg,
10
+ spotSvg,
11
+ title,
12
+ subtitle,
13
+ });
14
+ };
15
+
16
+ const getIllustrationDataSync = nameProp => {
17
+ let set = "fiori";
18
+
19
+ if (nameProp.startsWith("Tnt")) {
20
+ set = "tnt";
21
+ nameProp = nameProp.replace(/^Tnt/, "");
22
+ }
23
+
24
+ return registry.get(`${set}/${nameProp}`) || ILLUSTRATION_NOT_FOUND;
25
+ };
26
+
27
+ export {
28
+ getIllustrationDataSync,
29
+ registerIllustration,
30
+ };
@@ -1,17 +1,13 @@
1
- import { fetchJsonOnce } from "../util/FetchHelper.js";
2
1
  import { attachLanguageChange } from "../locale/languageChange.js";
3
2
  import getLocale from "../locale/getLocale.js";
4
- import { getFeature } from "../FeaturesRegistry.js";
5
3
  import { DEFAULT_LOCALE, SUPPORTED_LOCALES } from "../generated/AssetParameters.js";
6
- import { getEffectiveAssetPath } from "../util/EffectiveAssetPath.js";
7
-
8
- const resources = new Map();
9
- const cldrData = {};
10
- const cldrUrls = {};
4
+ import { getFeature } from "../FeaturesRegistry.js";
11
5
 
12
- // externally configurable mapping function for resolving (localeId -> URL)
13
- // default implementation - ui5 CDN
14
- let cldrMappingFn = locale => `https://ui5.sap.com/1.60.2/resources/sap/ui/core/cldr/${locale}.json`;
6
+ const localeDataMap = new Map();
7
+ const loaders = new Map();
8
+ const cldrPromises = new Map();
9
+ const reportedErrors = new Set();
10
+ let warningShown = false;
15
11
 
16
12
  const M_ISO639_OLD_TO_NEW = {
17
13
  "iw": "he",
@@ -20,6 +16,22 @@ const M_ISO639_OLD_TO_NEW = {
20
16
  "sh": "sr",
21
17
  };
22
18
 
19
+ const DEV_MODE = false;
20
+
21
+ const _showAssetsWarningOnce = localeId => {
22
+ if (warningShown) {
23
+ return;
24
+ }
25
+
26
+ if (!DEV_MODE) {
27
+ console.warn(`[LocaleData] Supported locale "${localeId}" not configured, import the "Assets.js" module from the webcomponents package you are using.`); /* eslint-disable-line */
28
+ } else {
29
+ console.warn(`[LocaleData] Note: in dev mode, CLDR assets might be disabled for performance reasons. Try running "ENABLE_CLDR=1 yarn start" to test CLDR assets.`); /* eslint-disable-line */
30
+ }
31
+
32
+ warningShown = true;
33
+ };
34
+
23
35
  const calcLocale = (language, region, script) => {
24
36
  // normalize language and handle special cases
25
37
  language = (language && M_ISO639_OLD_TO_NEW[language]) || language;
@@ -38,85 +50,100 @@ const calcLocale = (language, region, script) => {
38
50
 
39
51
  // try language + region
40
52
  let localeId = `${language}_${region}`;
41
- if (!SUPPORTED_LOCALES.includes(localeId)) {
42
- // fallback to language only
43
- localeId = language;
53
+ if (SUPPORTED_LOCALES.includes(localeId)) {
54
+ if (loaders.has(localeId)) {
55
+ // supported and has loader
56
+ return localeId;
57
+ }
58
+
59
+ // supported, no loader - fallback to default and warn
60
+ _showAssetsWarningOnce(localeId);
61
+ return DEFAULT_LOCALE;
44
62
  }
45
- if (!SUPPORTED_LOCALES.includes(localeId)) {
46
- // fallback to english
47
- localeId = DEFAULT_LOCALE;
63
+
64
+ // not supported, try language only
65
+ localeId = language;
66
+ if (SUPPORTED_LOCALES.includes(localeId)) {
67
+ if (loaders.has(localeId)) {
68
+ // supported and has loader
69
+ return localeId;
70
+ }
71
+
72
+ // supported, no loader - fallback to default and warn
73
+ _showAssetsWarningOnce(localeId);
74
+ return DEFAULT_LOCALE;
48
75
  }
49
76
 
50
- return localeId;
77
+ // not supported - fallback to default locale
78
+ return DEFAULT_LOCALE;
51
79
  };
52
80
 
81
+ // internal set data
82
+ const setLocaleData = (localeId, content) => {
83
+ localeDataMap.set(localeId, content);
84
+ };
53
85
 
54
- const resolveMissingMappings = () => {
55
- if (!cldrMappingFn) {
56
- return;
86
+ // external getSync
87
+ const getLocaleData = localeId => {
88
+ // if there is no loader, the default fallback was fetched and a warning was given - use default locale instead
89
+ if (!loaders.has(localeId)) {
90
+ localeId = DEFAULT_LOCALE;
57
91
  }
58
92
 
59
- const missingLocales = SUPPORTED_LOCALES.filter(locale => !cldrData[locale] && !cldrUrls[locale]);
60
- missingLocales.forEach(locale => {
61
- cldrUrls[locale] = cldrMappingFn(locale);
62
- });
63
- };
93
+ const content = localeDataMap.get(localeId);
94
+ if (!content) {
95
+ throw new Error(`CLDR data for locale ${localeId} is not loaded!`);
96
+ }
64
97
 
65
- const registerModuleContent = (moduleName, content) => {
66
- resources.set(moduleName, content);
98
+ return content;
67
99
  };
68
100
 
69
- const getModuleContent = moduleName => {
70
- const moduleContent = resources.get(moduleName);
71
- if (moduleContent) {
72
- return moduleContent;
73
- }
101
+ // load bundle over the network once
102
+ const _loadCldrOnce = localeId => {
103
+ const loadCldr = loaders.get(localeId);
74
104
 
75
- const missingModule = moduleName.match(/sap\/ui\/core\/cldr\/(\w+)\.json/);
76
- if (missingModule) {
77
- throw new Error(`CLDR data for locale ${missingModule[1]} is not loaded!`);
105
+ if (!cldrPromises.get(localeId)) {
106
+ cldrPromises.set(localeId, loadCldr(localeId));
78
107
  }
79
108
 
80
- throw new Error(`Unknown module ${moduleName}`);
109
+ return cldrPromises.get(localeId);
81
110
  };
82
111
 
112
+ // external getAsync
83
113
  const fetchCldr = async (language, region, script) => {
84
- resolveMissingMappings();
85
114
  const localeId = calcLocale(language, region, script);
86
115
 
87
- let cldrObj = cldrData[localeId];
88
- const url = cldrUrls[localeId];
89
-
116
+ // reuse OpenUI5 CLDR if present
90
117
  const OpenUI5Support = getFeature("OpenUI5Support");
91
- if (!cldrObj && OpenUI5Support) {
92
- cldrObj = OpenUI5Support.getLocaleDataObject();
118
+ if (OpenUI5Support) {
119
+ const cldrContent = OpenUI5Support.getLocaleDataObject();
120
+ if (cldrContent) {
121
+ // only if openui5 actually returned valid content
122
+ setLocaleData(localeId, cldrContent);
123
+ return;
124
+ }
93
125
  }
94
126
 
95
- if (cldrObj) {
96
- // inlined from build or fetched independently
97
- registerModuleContent(`sap/ui/core/cldr/${localeId}.json`, cldrObj);
98
- } else if (url) {
99
- // fetch it
100
- const cldrContent = await fetchJsonOnce(getEffectiveAssetPath(url));
101
- registerModuleContent(`sap/ui/core/cldr/${localeId}.json`, cldrContent);
127
+ // fetch it
128
+ try {
129
+ const cldrContent = await _loadCldrOnce(localeId);
130
+ setLocaleData(localeId, cldrContent);
131
+ } catch (e) {
132
+ if (!reportedErrors.has(e.message)) {
133
+ reportedErrors.add(e.message);
134
+ console.error(e.message); /* eslint-disable-line */
135
+ }
102
136
  }
103
137
  };
104
138
 
105
- const registerCldr = (locale, url) => {
106
- cldrUrls[locale] = url;
107
- };
108
-
109
- const setCldrData = (locale, data) => {
110
- cldrData[locale] = data;
139
+ const registerLocaleDataLoader = (localeId, loader) => {
140
+ loaders.set(localeId, loader);
111
141
  };
112
142
 
113
- const getCldrData = locale => {
114
- return cldrData[locale];
115
- };
116
-
117
- const _registerMappingFunction = mappingFn => {
118
- cldrMappingFn = mappingFn;
119
- };
143
+ // register default loader for "en" from ui5 CDN (dev workflow without assets)
144
+ registerLocaleDataLoader("en", async runtimeLocaleId => {
145
+ return (await fetch(`https://ui5.sap.com/1.60.2/resources/sap/ui/core/cldr/en.json`)).json();
146
+ });
120
147
 
121
148
  // When the language changes dynamically (the user calls setLanguage),
122
149
  // re-fetch the required CDRD data.
@@ -126,10 +153,7 @@ attachLanguageChange(() => {
126
153
  });
127
154
 
128
155
  export {
156
+ registerLocaleDataLoader,
129
157
  fetchCldr,
130
- registerCldr,
131
- setCldrData,
132
- getCldrData,
133
- getModuleContent,
134
- _registerMappingFunction,
158
+ getLocaleData,
135
159
  };
@@ -1,10 +1,7 @@
1
- import { fetchJsonOnce, fetchTextOnce } from "../util/FetchHelper.js";
2
1
  import { DEFAULT_THEME } from "../generated/AssetParameters.js";
3
- import getFileExtension from "../util/getFileExtension.js";
4
- import { getEffectiveAssetPath } from "../util/EffectiveAssetPath.js";
5
2
 
6
- const themeURLs = new Map();
7
3
  const themeStyles = new Map();
4
+ const loaders = new Map();
8
5
  const registeredPackages = new Set();
9
6
  const registeredThemes = new Set();
10
7
 
@@ -16,29 +13,19 @@ const registeredThemes = new Set();
16
13
  * Example usage:
17
14
  * 1) Pass the CSS Vars as a string directly.
18
15
  * registerThemeProperties("my-package", "my_theme", ":root{--var1: red;}");
19
- * 2) Pass the CSS Vars as an object directly
20
- * registerThemeProperties("my-package", "my_theme", {"_": ":root{--var1: red;}"});
21
- * 3) Pass a URL to a CSS file, containing the CSS Vars. Will be fetched on demand, not upon registration.
22
- * registerThemeProperties("my-package", "my_theme", "http://url/to/my/theme.css");
23
- * 4) Pass a URL to a JSON file, containing the CSS Vars in its "_" property. Will be fetched on demand, not upon registration.
24
- * registerThemeProperties("my-package", "my_theme", "http://url/to/my/theme.json");
25
16
  *
26
17
  * @public
27
18
  * @param packageName - the NPM package for which CSS Vars are registered
28
19
  * @param themeName - the theme which the CSS Vars implement
29
- * @param style - can be one of four options: a string, an object with a "_" property, URL to a CSS file, or URL to a JSON file with a "_" property
20
+ * @param style - the style content directly
21
+ * @deprecated
30
22
  */
31
- const registerThemeProperties = (packageName, themeName, style) => {
32
- if (style._) {
33
- // JSON object like ({"_": ":root"})
34
- themeStyles.set(`${packageName}_${themeName}`, style._);
35
- } else if (style.includes(":root") || style === "") {
36
- // pure string, including empty string
37
- themeStyles.set(`${packageName}_${themeName}`, style);
38
- } else {
39
- // url for fetching
40
- themeURLs.set(`${packageName}_${themeName}`, style);
41
- }
23
+ const registerThemeProperties = (_packageName, _themeName, _style) => {
24
+ throw new Error("`registerThemeProperties` has been depracated. Use `registerThemePropertiesLoader` instead.");
25
+ };
26
+
27
+ const registerThemePropertiesLoader = (packageName, themeName, loader) => {
28
+ loaders.set(`${packageName}/${themeName}`, loader);
42
29
  registeredPackages.add(packageName);
43
30
  registeredThemes.add(themeName);
44
31
  };
@@ -55,23 +42,25 @@ const getThemeProperties = async (packageName, themeName) => {
55
42
  return themeStyles.get(`${packageName}_${DEFAULT_THEME}`);
56
43
  }
57
44
 
58
- const data = await fetchThemeProperties(packageName, themeName);
45
+ const loader = loaders.get(`${packageName}/${themeName}`);
46
+ if (!loader) {
47
+ // no themes for package
48
+ console.error(`Theme [${themeName}] not registered for package [${packageName}]`); /* eslint-disable-line */
49
+ return;
50
+ }
51
+ let data;
52
+ try {
53
+ data = await loader(themeName);
54
+ } catch (e) {
55
+ console.error(packageName, e.message); /* eslint-disable-line */
56
+ return;
57
+ }
59
58
  const themeProps = data._ || data;
60
59
 
61
60
  themeStyles.set(`${packageName}_${themeName}`, themeProps);
62
61
  return themeProps;
63
62
  };
64
63
 
65
- const fetchThemeProperties = async (packageName, themeName) => {
66
- const url = themeURLs.get(`${packageName}_${themeName}`);
67
-
68
- if (!url) {
69
- throw new Error(`You have to import the ${packageName}/dist/Assets.js module to switch to additional themes`);
70
- }
71
-
72
- return getFileExtension(url) === ".css" ? fetchTextOnce(url) : fetchJsonOnce(getEffectiveAssetPath(url));
73
- };
74
-
75
64
  const getRegisteredPackages = () => {
76
65
  return registeredPackages;
77
66
  };
@@ -81,6 +70,7 @@ const isThemeRegistered = theme => {
81
70
  };
82
71
 
83
72
  export {
73
+ registerThemePropertiesLoader,
84
74
  registerThemeProperties,
85
75
  getThemeProperties,
86
76
  getRegisteredPackages,