@ui5/webcomponents-base 0.0.0-32b659ddc → 0.0.0-35e2c9666

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 (454) hide show
  1. package/.eslintignore +4 -0
  2. package/CHANGELOG.md +329 -0
  3. package/README.md +26 -2
  4. package/bundle.esm.js +17 -12
  5. package/dist/AssetRegistry.js +8 -6
  6. package/dist/Boot.js +59 -0
  7. package/dist/CSP.js +59 -0
  8. package/dist/CustomElementsRegistry.js +95 -0
  9. package/dist/CustomElementsScope.js +108 -0
  10. package/dist/DOMObserver.js +65 -0
  11. package/dist/Device.js +69 -776
  12. package/dist/EventProvider.js +38 -26
  13. package/dist/FeaturesRegistry.js +4 -1
  14. package/dist/FontFace.js +19 -62
  15. package/dist/InitialConfiguration.js +46 -10
  16. package/dist/Keys.js +295 -0
  17. package/dist/ManagedStyles.js +83 -0
  18. package/dist/MediaRange.js +109 -0
  19. package/dist/PropertiesFileFormat.js +95 -0
  20. package/dist/Render.js +175 -0
  21. package/dist/RenderQueue.js +41 -17
  22. package/dist/RenderScheduler.js +24 -145
  23. package/dist/Runtimes.js +107 -0
  24. package/dist/StaticArea.js +1 -39
  25. package/dist/StaticAreaItem.js +61 -50
  26. package/dist/SystemCSSVars.js +10 -0
  27. package/dist/Theming.js +3 -54
  28. package/dist/UI5Element.js +454 -300
  29. package/dist/UI5ElementMetadata.js +182 -19
  30. package/dist/asset-registries/Icons.js +129 -14
  31. package/dist/asset-registries/Illustrations.js +30 -0
  32. package/dist/asset-registries/LocaleData.js +112 -56
  33. package/dist/asset-registries/Themes.js +35 -32
  34. package/dist/asset-registries/i18n.js +80 -33
  35. package/dist/assets-meta/IconCollectionsAlias.js +18 -0
  36. package/dist/config/AnimationMode.js +11 -1
  37. package/dist/config/CalendarType.js +3 -7
  38. package/dist/config/Language.js +58 -2
  39. package/dist/config/Theme.js +27 -2
  40. package/dist/css/FontFace.css +45 -0
  41. package/dist/css/OverrideFontFace.css +32 -0
  42. package/dist/css/SystemCSSVars.css +17 -0
  43. package/dist/delegate/ItemNavigation.js +245 -172
  44. package/dist/delegate/ResizeHandler.js +78 -38
  45. package/dist/delegate/ScrollEnablement.js +101 -19
  46. package/dist/features/F6Navigation.js +108 -0
  47. package/dist/features/OpenUI5Support.js +56 -7
  48. package/dist/generated/AssetParameters.js +13 -0
  49. package/dist/generated/VersionInfo.js +10 -0
  50. package/dist/generated/css/FontFace.css.js +5 -0
  51. package/dist/generated/css/OverrideFontFace.css.js +5 -0
  52. package/dist/generated/css/SystemCSSVars.css.js +5 -0
  53. package/dist/getSharedResource.js +30 -0
  54. package/dist/i18nBundle.js +62 -11
  55. package/dist/isLegacyBrowser.js +3 -0
  56. package/dist/{Locale.js → locale/Locale.js} +0 -10
  57. package/dist/locale/RTLAwareRegistry.js +14 -0
  58. package/dist/locale/applyDirection.js +17 -0
  59. package/dist/locale/directionChange.js +32 -0
  60. package/dist/locale/getEffectiveDir.js +28 -0
  61. package/dist/locale/getLocale.js +41 -0
  62. package/dist/locale/languageChange.js +22 -0
  63. package/dist/locale/nextFallbackLocale.js +28 -0
  64. package/{src/util → dist/locale}/normalizeLocale.js +8 -31
  65. package/dist/renderer/LitRenderer.js +26 -7
  66. package/dist/renderer/directives/style-map.js +72 -0
  67. package/dist/renderer/executeTemplate.js +17 -0
  68. package/dist/resources/bundle.esm.js +20 -106
  69. package/dist/resources/bundle.esm.js.map +1 -1
  70. package/dist/sap/base/Log.js +241 -0
  71. package/dist/sap/base/assert.js +8 -0
  72. package/dist/sap/base/security/URLListValidator.js +148 -0
  73. package/dist/sap/base/security/encodeCSS.js +14 -0
  74. package/dist/sap/base/security/encodeXML.js +23 -0
  75. package/dist/sap/base/security/sanitizeHTML.js +16 -0
  76. package/dist/sap/base/strings/toHex.js +8 -0
  77. package/dist/sap/base/util/now.js +7 -0
  78. package/dist/sap/ui/thirdparty/caja-html-sanitizer.js +3585 -0
  79. package/dist/test-resources/assets/Themes.js +10 -6
  80. package/dist/test-resources/elements/Parent.js +6 -2
  81. package/dist/test-resources/elements/WithStaticArea.js +77 -0
  82. package/dist/test-resources/pages/AllTestElements.html +5 -3
  83. package/dist/test-resources/pages/Configuration.html +0 -2
  84. package/dist/test-resources/pages/ConfigurationScript.html +1 -3
  85. package/dist/test-resources/pages/assets/messagebundle_de.properties +1 -0
  86. package/dist/test-resources/pages/assets/messagebundle_en.properties +1 -0
  87. package/dist/test-resources/pages/assets/messagebundle_es.properties +1 -0
  88. package/dist/test-resources/pages/assets/messagebundle_fr.properties +1 -0
  89. package/dist/test-resources/pages/i18n.html +33 -0
  90. package/dist/test-resources/specs/ConfigurationChange.spec.js +11 -9
  91. package/dist/test-resources/specs/ConfigurationScript.spec.js +25 -23
  92. package/dist/test-resources/specs/ConfigurationURL.spec.js +65 -17
  93. package/dist/test-resources/specs/CustomTheme.spec.js +9 -7
  94. package/dist/test-resources/specs/EventProvider.spec.js +63 -0
  95. package/dist/test-resources/specs/StaticArea.spec.js +78 -0
  96. package/dist/test-resources/specs/Theming.spec.js +12 -10
  97. package/dist/test-resources/specs/UI5ElementInvalidation.js +54 -70
  98. package/dist/test-resources/specs/UI5ElementLifecycle.js +19 -14
  99. package/dist/test-resources/specs/UI5ElementListenForChildPropChanges.spec.js +25 -51
  100. package/dist/test-resources/specs/UI5ElementMetadataExt.js +9 -7
  101. package/dist/test-resources/specs/UI5ElementPropertyValidation.js +7 -5
  102. package/dist/test-resources/specs/UI5ElementPropsAndAttrs.spec.js +37 -35
  103. package/dist/test-resources/specs/UI5ElementShadowDOM.js +10 -8
  104. package/dist/test-resources/specs/UI5ElementSlots.js +10 -8
  105. package/dist/theming/CustomStyle.js +47 -6
  106. package/dist/theming/ThemeLoaded.js +22 -0
  107. package/dist/theming/applyTheme.js +79 -0
  108. package/dist/theming/getConstructableStyle.js +30 -0
  109. package/dist/theming/getEffectiveLinksHrefs.js +20 -0
  110. package/dist/theming/getEffectiveStyle.js +30 -0
  111. package/dist/theming/getStylesString.js +15 -0
  112. package/dist/theming/getThemeDesignerTheme.js +87 -0
  113. package/dist/theming/preloadLinks.js +23 -0
  114. package/dist/thirdparty/_merge.js +32 -0
  115. package/dist/thirdparty/isPlainObject.js +18 -0
  116. package/dist/thirdparty/merge.js +10 -0
  117. package/dist/types/CSSColor.js +9 -0
  118. package/{src/dates → dist/types}/CalendarType.js +2 -2
  119. package/dist/types/DataType.js +13 -1
  120. package/dist/types/Float.js +14 -0
  121. package/dist/types/Integer.js +4 -0
  122. package/dist/types/InvisibleMessageMode.js +30 -0
  123. package/dist/types/ItemNavigationBehavior.js +2 -7
  124. package/dist/types/NavigationMode.js +1 -0
  125. package/dist/types/PopupState.js +1 -1
  126. package/dist/types/ValueState.js +1 -1
  127. package/dist/updateShadowRoot.js +30 -0
  128. package/dist/util/AriaLabelHelper.js +41 -0
  129. package/dist/util/Caret.js +45 -0
  130. package/dist/util/ColorConversion.js +370 -0
  131. package/dist/util/FocusableElements.js +30 -11
  132. package/dist/util/HTMLSanitizer.js +7 -0
  133. package/dist/util/InvisibleMessage.js +60 -0
  134. package/dist/util/PopupUtils.js +93 -0
  135. package/dist/util/SlotsHelper.js +43 -0
  136. package/dist/util/TabbableElements.js +9 -2
  137. package/dist/util/arraysAreEqual.js +15 -0
  138. package/dist/util/clamp.js +12 -0
  139. package/dist/util/createLinkInHead.js +19 -0
  140. package/dist/util/debounce.js +17 -0
  141. package/dist/util/detectNavigatorLanguage.js +3 -1
  142. package/dist/util/escapeRegex.js +10 -0
  143. package/dist/util/findNodeOwner.js +35 -0
  144. package/dist/util/generateHighlightedMarkup.js +42 -0
  145. package/dist/util/getActiveElement.js +11 -0
  146. package/dist/util/getClassCopy.js +10 -0
  147. package/dist/util/getEffectiveContentDensity.js +5 -0
  148. package/dist/util/getFileExtension.js +21 -0
  149. package/dist/util/getSingletonElementInstance.js +13 -0
  150. package/dist/util/isElementInView.js +15 -0
  151. package/dist/util/isNodeHidden.js +1 -5
  152. package/dist/util/isNodeTabbable.js +4 -4
  153. package/dist/util/isValidPropertyName.js +11 -2
  154. package/dist/util/setToArray.js +10 -0
  155. package/hash.txt +1 -0
  156. package/index.js +1 -1
  157. package/lib/generate-asset-parameters/index.js +21 -0
  158. package/lib/generate-styles/index.js +18 -0
  159. package/lib/generate-version-info/index.js +27 -0
  160. package/package-scripts.js +38 -18
  161. package/package.json +19 -13
  162. package/src/AssetRegistry.js +8 -6
  163. package/src/Boot.js +59 -0
  164. package/src/CSP.js +59 -0
  165. package/src/CustomElementsRegistry.js +95 -0
  166. package/src/CustomElementsScope.js +108 -0
  167. package/src/DOMObserver.js +65 -0
  168. package/src/Device.js +69 -776
  169. package/src/EventProvider.js +38 -26
  170. package/src/FeaturesRegistry.js +4 -1
  171. package/src/FontFace.js +19 -62
  172. package/src/InitialConfiguration.js +46 -10
  173. package/src/Keys.js +295 -0
  174. package/src/ManagedStyles.js +83 -0
  175. package/src/MediaRange.js +109 -0
  176. package/src/PropertiesFileFormat.js +95 -0
  177. package/src/Render.js +175 -0
  178. package/src/RenderQueue.js +41 -17
  179. package/src/RenderScheduler.js +24 -145
  180. package/src/Runtimes.js +107 -0
  181. package/src/StaticArea.js +1 -39
  182. package/src/StaticAreaItem.js +61 -50
  183. package/src/SystemCSSVars.js +10 -0
  184. package/src/Theming.js +3 -54
  185. package/src/UI5Element.js +454 -300
  186. package/src/UI5ElementMetadata.js +182 -19
  187. package/src/asset-registries/Icons.js +129 -14
  188. package/src/asset-registries/Illustrations.js +30 -0
  189. package/src/asset-registries/LocaleData.js +112 -56
  190. package/src/asset-registries/Themes.js +35 -32
  191. package/src/asset-registries/i18n.js +80 -33
  192. package/src/assets-meta/IconCollectionsAlias.js +18 -0
  193. package/src/config/AnimationMode.js +11 -1
  194. package/src/config/CalendarType.js +3 -7
  195. package/src/config/Language.js +58 -2
  196. package/src/config/Theme.js +27 -2
  197. package/src/css/FontFace.css +45 -0
  198. package/src/css/OverrideFontFace.css +32 -0
  199. package/src/css/SystemCSSVars.css +17 -0
  200. package/src/delegate/ItemNavigation.js +245 -172
  201. package/src/delegate/ResizeHandler.js +78 -38
  202. package/src/delegate/ScrollEnablement.js +101 -19
  203. package/src/features/F6Navigation.js +108 -0
  204. package/src/features/OpenUI5Support.js +56 -7
  205. package/src/getSharedResource.js +30 -0
  206. package/src/i18nBundle.js +62 -11
  207. package/src/isLegacyBrowser.js +3 -0
  208. package/src/{Locale.js → locale/Locale.js} +0 -10
  209. package/src/locale/RTLAwareRegistry.js +14 -0
  210. package/src/locale/applyDirection.js +17 -0
  211. package/src/locale/directionChange.js +32 -0
  212. package/src/locale/getEffectiveDir.js +28 -0
  213. package/src/locale/getLocale.js +41 -0
  214. package/src/locale/languageChange.js +22 -0
  215. package/src/locale/nextFallbackLocale.js +28 -0
  216. package/{dist/util → src/locale}/normalizeLocale.js +8 -31
  217. package/src/renderer/LitRenderer.js +26 -7
  218. package/src/renderer/directives/style-map.js +72 -0
  219. package/src/renderer/executeTemplate.js +17 -0
  220. package/src/theming/CustomStyle.js +47 -6
  221. package/src/theming/ThemeLoaded.js +22 -0
  222. package/src/theming/applyTheme.js +79 -0
  223. package/src/theming/getConstructableStyle.js +30 -0
  224. package/src/theming/getEffectiveLinksHrefs.js +20 -0
  225. package/src/theming/getEffectiveStyle.js +30 -0
  226. package/src/theming/getStylesString.js +15 -0
  227. package/src/theming/getThemeDesignerTheme.js +87 -0
  228. package/src/theming/preloadLinks.js +23 -0
  229. package/src/thirdparty/_merge.js +32 -0
  230. package/src/thirdparty/isPlainObject.js +18 -0
  231. package/src/thirdparty/merge.js +10 -0
  232. package/src/types/CSSColor.js +9 -0
  233. package/{dist/dates → src/types}/CalendarType.js +2 -2
  234. package/src/types/DataType.js +13 -1
  235. package/src/types/Float.js +14 -0
  236. package/src/types/Integer.js +4 -0
  237. package/src/types/InvisibleMessageMode.js +30 -0
  238. package/src/types/ItemNavigationBehavior.js +2 -7
  239. package/src/types/NavigationMode.js +1 -0
  240. package/src/types/PopupState.js +1 -1
  241. package/src/types/ValueState.js +1 -1
  242. package/src/updateShadowRoot.js +30 -0
  243. package/src/util/AriaLabelHelper.js +41 -0
  244. package/src/util/Caret.js +45 -0
  245. package/src/util/ColorConversion.js +370 -0
  246. package/src/util/FocusableElements.js +30 -11
  247. package/src/util/HTMLSanitizer.js +7 -0
  248. package/src/util/InvisibleMessage.js +60 -0
  249. package/src/util/PopupUtils.js +93 -0
  250. package/src/util/SlotsHelper.js +43 -0
  251. package/src/util/TabbableElements.js +9 -2
  252. package/src/util/arraysAreEqual.js +15 -0
  253. package/src/util/clamp.js +12 -0
  254. package/src/util/createLinkInHead.js +19 -0
  255. package/src/util/debounce.js +17 -0
  256. package/src/util/detectNavigatorLanguage.js +3 -1
  257. package/src/util/escapeRegex.js +10 -0
  258. package/src/util/findNodeOwner.js +35 -0
  259. package/src/util/generateHighlightedMarkup.js +42 -0
  260. package/src/util/getActiveElement.js +11 -0
  261. package/src/util/getClassCopy.js +10 -0
  262. package/src/util/getEffectiveContentDensity.js +5 -0
  263. package/src/util/getFileExtension.js +21 -0
  264. package/src/util/getSingletonElementInstance.js +13 -0
  265. package/src/util/isElementInView.js +15 -0
  266. package/src/util/isNodeHidden.js +1 -5
  267. package/src/util/isNodeTabbable.js +4 -4
  268. package/src/util/isValidPropertyName.js +11 -2
  269. package/src/util/setToArray.js +10 -0
  270. package/used-modules.txt +10 -0
  271. package/bundle.es5.js +0 -28
  272. package/dist/Assets.js +0 -2
  273. package/dist/CSS.js +0 -48
  274. package/dist/FormatSettings.js +0 -31
  275. package/dist/LocaleProvider.js +0 -34
  276. package/dist/ResourceLoaderOverrides.js +0 -38
  277. package/dist/SVGIconRegistry.js +0 -54
  278. package/dist/boot.js +0 -32
  279. package/dist/compatibility/DOMObserver.js +0 -62
  280. package/dist/compatibility/patchNodeValue.js +0 -24
  281. package/dist/compatibility/whenPolyfillLoaded.js +0 -26
  282. package/dist/dates/CalendarDate.js +0 -203
  283. package/dist/dates/CalendarUtils.js +0 -99
  284. package/dist/delegate/CustomResize.js +0 -78
  285. package/dist/delegate/NativeResize.js +0 -44
  286. package/dist/events/PseudoEvents.js +0 -58
  287. package/dist/features/browsersupport/Edge.js +0 -6
  288. package/dist/features/browsersupport/IE11.js +0 -41
  289. package/dist/features/calendar/Buddhist.js +0 -1
  290. package/dist/features/calendar/Islamic.js +0 -1
  291. package/dist/features/calendar/Japanese.js +0 -1
  292. package/dist/features/calendar/Persian.js +0 -1
  293. package/dist/generated/assets/cldr/sap/ui/core/cldr/ar.json +0 -5906
  294. package/dist/generated/assets/cldr/sap/ui/core/cldr/ar_EG.json +0 -5906
  295. package/dist/generated/assets/cldr/sap/ui/core/cldr/ar_SA.json +0 -5906
  296. package/dist/generated/assets/cldr/sap/ui/core/cldr/bg.json +0 -4979
  297. package/dist/generated/assets/cldr/sap/ui/core/cldr/ca.json +0 -4996
  298. package/dist/generated/assets/cldr/sap/ui/core/cldr/cs.json +0 -5498
  299. package/dist/generated/assets/cldr/sap/ui/core/cldr/da.json +0 -4888
  300. package/dist/generated/assets/cldr/sap/ui/core/cldr/de.json +0 -4916
  301. package/dist/generated/assets/cldr/sap/ui/core/cldr/de_AT.json +0 -4917
  302. package/dist/generated/assets/cldr/sap/ui/core/cldr/de_CH.json +0 -4915
  303. package/dist/generated/assets/cldr/sap/ui/core/cldr/el.json +0 -4883
  304. package/dist/generated/assets/cldr/sap/ui/core/cldr/el_CY.json +0 -4883
  305. package/dist/generated/assets/cldr/sap/ui/core/cldr/en.json +0 -4970
  306. package/dist/generated/assets/cldr/sap/ui/core/cldr/en_AU.json +0 -4962
  307. package/dist/generated/assets/cldr/sap/ui/core/cldr/en_GB.json +0 -4971
  308. package/dist/generated/assets/cldr/sap/ui/core/cldr/en_HK.json +0 -4977
  309. package/dist/generated/assets/cldr/sap/ui/core/cldr/en_IE.json +0 -4971
  310. package/dist/generated/assets/cldr/sap/ui/core/cldr/en_IN.json +0 -4972
  311. package/dist/generated/assets/cldr/sap/ui/core/cldr/en_NZ.json +0 -4971
  312. package/dist/generated/assets/cldr/sap/ui/core/cldr/en_PG.json +0 -4972
  313. package/dist/generated/assets/cldr/sap/ui/core/cldr/en_SG.json +0 -4973
  314. package/dist/generated/assets/cldr/sap/ui/core/cldr/en_ZA.json +0 -4972
  315. package/dist/generated/assets/cldr/sap/ui/core/cldr/es.json +0 -4912
  316. package/dist/generated/assets/cldr/sap/ui/core/cldr/es_AR.json +0 -4914
  317. package/dist/generated/assets/cldr/sap/ui/core/cldr/es_BO.json +0 -4913
  318. package/dist/generated/assets/cldr/sap/ui/core/cldr/es_CL.json +0 -4914
  319. package/dist/generated/assets/cldr/sap/ui/core/cldr/es_CO.json +0 -4913
  320. package/dist/generated/assets/cldr/sap/ui/core/cldr/es_MX.json +0 -4915
  321. package/dist/generated/assets/cldr/sap/ui/core/cldr/es_PE.json +0 -4913
  322. package/dist/generated/assets/cldr/sap/ui/core/cldr/es_UY.json +0 -4915
  323. package/dist/generated/assets/cldr/sap/ui/core/cldr/es_VE.json +0 -4914
  324. package/dist/generated/assets/cldr/sap/ui/core/cldr/et.json +0 -4967
  325. package/dist/generated/assets/cldr/sap/ui/core/cldr/fa.json +0 -4883
  326. package/dist/generated/assets/cldr/sap/ui/core/cldr/fi.json +0 -5008
  327. package/dist/generated/assets/cldr/sap/ui/core/cldr/fr.json +0 -4979
  328. package/dist/generated/assets/cldr/sap/ui/core/cldr/fr_BE.json +0 -4979
  329. package/dist/generated/assets/cldr/sap/ui/core/cldr/fr_CA.json +0 -4973
  330. package/dist/generated/assets/cldr/sap/ui/core/cldr/fr_CH.json +0 -4997
  331. package/dist/generated/assets/cldr/sap/ui/core/cldr/fr_LU.json +0 -4979
  332. package/dist/generated/assets/cldr/sap/ui/core/cldr/he.json +0 -5378
  333. package/dist/generated/assets/cldr/sap/ui/core/cldr/hi.json +0 -4829
  334. package/dist/generated/assets/cldr/sap/ui/core/cldr/hr.json +0 -4919
  335. package/dist/generated/assets/cldr/sap/ui/core/cldr/hu.json +0 -4856
  336. package/dist/generated/assets/cldr/sap/ui/core/cldr/id.json +0 -4658
  337. package/dist/generated/assets/cldr/sap/ui/core/cldr/it.json +0 -4950
  338. package/dist/generated/assets/cldr/sap/ui/core/cldr/it_CH.json +0 -4950
  339. package/dist/generated/assets/cldr/sap/ui/core/cldr/ja.json +0 -4830
  340. package/dist/generated/assets/cldr/sap/ui/core/cldr/kk.json +0 -4725
  341. package/dist/generated/assets/cldr/sap/ui/core/cldr/ko.json +0 -4738
  342. package/dist/generated/assets/cldr/sap/ui/core/cldr/lt.json +0 -5481
  343. package/dist/generated/assets/cldr/sap/ui/core/cldr/lv.json +0 -5112
  344. package/dist/generated/assets/cldr/sap/ui/core/cldr/ms.json +0 -4515
  345. package/dist/generated/assets/cldr/sap/ui/core/cldr/nb.json +0 -4977
  346. package/dist/generated/assets/cldr/sap/ui/core/cldr/nl.json +0 -4884
  347. package/dist/generated/assets/cldr/sap/ui/core/cldr/nl_BE.json +0 -4884
  348. package/dist/generated/assets/cldr/sap/ui/core/cldr/pl.json +0 -5176
  349. package/dist/generated/assets/cldr/sap/ui/core/cldr/pt.json +0 -4805
  350. package/dist/generated/assets/cldr/sap/ui/core/cldr/pt_PT.json +0 -4940
  351. package/dist/generated/assets/cldr/sap/ui/core/cldr/ro.json +0 -5090
  352. package/dist/generated/assets/cldr/sap/ui/core/cldr/ru.json +0 -5407
  353. package/dist/generated/assets/cldr/sap/ui/core/cldr/ru_UA.json +0 -5407
  354. package/dist/generated/assets/cldr/sap/ui/core/cldr/sk.json +0 -5370
  355. package/dist/generated/assets/cldr/sap/ui/core/cldr/sl.json +0 -5340
  356. package/dist/generated/assets/cldr/sap/ui/core/cldr/sr.json +0 -5126
  357. package/dist/generated/assets/cldr/sap/ui/core/cldr/sv.json +0 -5011
  358. package/dist/generated/assets/cldr/sap/ui/core/cldr/th.json +0 -4797
  359. package/dist/generated/assets/cldr/sap/ui/core/cldr/tr.json +0 -4979
  360. package/dist/generated/assets/cldr/sap/ui/core/cldr/uk.json +0 -5353
  361. package/dist/generated/assets/cldr/sap/ui/core/cldr/vi.json +0 -4673
  362. package/dist/generated/assets/cldr/sap/ui/core/cldr/zh_CN.json +0 -4632
  363. package/dist/generated/assets/cldr/sap/ui/core/cldr/zh_HK.json +0 -4640
  364. package/dist/generated/assets/cldr/sap/ui/core/cldr/zh_SG.json +0 -4640
  365. package/dist/generated/assets/cldr/sap/ui/core/cldr/zh_TW.json +0 -4728
  366. package/dist/json-imports/LocaleData.js +0 -171
  367. package/dist/renderer/ifDefined.js +0 -21
  368. package/dist/resources/bundle.es5.js +0 -212
  369. package/dist/resources/bundle.es5.js.map +0 -1
  370. package/dist/shims/Core-shim.js +0 -53
  371. package/dist/test-resources/dev-helpers/ExternalThemePresent.js +0 -3
  372. package/dist/theming/StyleInjection.js +0 -67
  373. package/dist/thirdparty/Array.from.js +0 -16
  374. package/dist/thirdparty/Array.prototype.fill.js +0 -44
  375. package/dist/thirdparty/Array.prototype.find.js +0 -46
  376. package/dist/thirdparty/Array.prototype.includes.js +0 -51
  377. package/dist/thirdparty/Element.prototype.closest.js +0 -11
  378. package/dist/thirdparty/Element.prototype.matches.js +0 -6
  379. package/dist/thirdparty/Map.prototype.keys.js +0 -9
  380. package/dist/thirdparty/Number.isInteger.js +0 -5
  381. package/dist/thirdparty/Number.isNaN.js +0 -1
  382. package/dist/thirdparty/Number.parseInt.js +0 -1
  383. package/dist/thirdparty/Object.assign.js +0 -31
  384. package/dist/thirdparty/Object.entries.js +0 -11
  385. package/dist/thirdparty/Symbol.js +0 -2
  386. package/dist/thirdparty/WeakSet.js +0 -27
  387. package/dist/thirdparty/events-polyfills.js +0 -89
  388. package/dist/thirdparty/fetch.js +0 -1
  389. package/dist/thirdparty/template.js +0 -600
  390. package/dist/util/CSSTransformUtils.js +0 -90
  391. package/dist/webcomponentsjs/LICENSE.md +0 -19
  392. package/dist/webcomponentsjs/README.md +0 -229
  393. package/dist/webcomponentsjs/bundles/webcomponents-ce.js +0 -63
  394. package/dist/webcomponentsjs/bundles/webcomponents-ce.js.map +0 -1
  395. package/dist/webcomponentsjs/bundles/webcomponents-sd-ce-pf.js +0 -297
  396. package/dist/webcomponentsjs/bundles/webcomponents-sd-ce-pf.js.map +0 -1
  397. package/dist/webcomponentsjs/bundles/webcomponents-sd-ce.js +0 -208
  398. package/dist/webcomponentsjs/bundles/webcomponents-sd-ce.js.map +0 -1
  399. package/dist/webcomponentsjs/bundles/webcomponents-sd.js +0 -166
  400. package/dist/webcomponentsjs/bundles/webcomponents-sd.js.map +0 -1
  401. package/dist/webcomponentsjs/custom-elements-es5-adapter.js +0 -15
  402. package/dist/webcomponentsjs/package.json +0 -46
  403. package/dist/webcomponentsjs/src/entrypoints/custom-elements-es5-adapter-index.js +0 -16
  404. package/dist/webcomponentsjs/src/entrypoints/webcomponents-bundle-index.js +0 -53
  405. package/dist/webcomponentsjs/src/entrypoints/webcomponents-ce-index.js +0 -17
  406. package/dist/webcomponentsjs/src/entrypoints/webcomponents-sd-ce-index.js +0 -19
  407. package/dist/webcomponentsjs/src/entrypoints/webcomponents-sd-ce-pf-index.js +0 -28
  408. package/dist/webcomponentsjs/src/entrypoints/webcomponents-sd-index.js +0 -18
  409. package/dist/webcomponentsjs/webcomponents-bundle.js +0 -298
  410. package/dist/webcomponentsjs/webcomponents-bundle.js.map +0 -1
  411. package/dist/webcomponentsjs/webcomponents-loader.js +0 -185
  412. package/src/Assets.js +0 -2
  413. package/src/CSS.js +0 -48
  414. package/src/FormatSettings.js +0 -31
  415. package/src/LocaleProvider.js +0 -34
  416. package/src/ResourceLoaderOverrides.js +0 -38
  417. package/src/SVGIconRegistry.js +0 -54
  418. package/src/boot.js +0 -32
  419. package/src/compatibility/DOMObserver.js +0 -62
  420. package/src/compatibility/patchNodeValue.js +0 -24
  421. package/src/compatibility/whenPolyfillLoaded.js +0 -26
  422. package/src/dates/CalendarDate.js +0 -203
  423. package/src/dates/CalendarUtils.js +0 -99
  424. package/src/delegate/CustomResize.js +0 -78
  425. package/src/delegate/NativeResize.js +0 -44
  426. package/src/events/PseudoEvents.js +0 -58
  427. package/src/features/browsersupport/Edge.js +0 -6
  428. package/src/features/browsersupport/IE11.js +0 -41
  429. package/src/features/calendar/Buddhist.js +0 -1
  430. package/src/features/calendar/Islamic.js +0 -1
  431. package/src/features/calendar/Japanese.js +0 -1
  432. package/src/features/calendar/Persian.js +0 -1
  433. package/src/json-imports/LocaleData.js +0 -171
  434. package/src/renderer/ifDefined.js +0 -21
  435. package/src/shims/Core-shim.js +0 -53
  436. package/src/theming/StyleInjection.js +0 -67
  437. package/src/thirdparty/Array.from.js +0 -16
  438. package/src/thirdparty/Array.prototype.fill.js +0 -44
  439. package/src/thirdparty/Array.prototype.find.js +0 -46
  440. package/src/thirdparty/Array.prototype.includes.js +0 -51
  441. package/src/thirdparty/Element.prototype.closest.js +0 -11
  442. package/src/thirdparty/Element.prototype.matches.js +0 -6
  443. package/src/thirdparty/Map.prototype.keys.js +0 -9
  444. package/src/thirdparty/Number.isInteger.js +0 -5
  445. package/src/thirdparty/Number.isNaN.js +0 -1
  446. package/src/thirdparty/Number.parseInt.js +0 -1
  447. package/src/thirdparty/Object.assign.js +0 -31
  448. package/src/thirdparty/Object.entries.js +0 -11
  449. package/src/thirdparty/Symbol.js +0 -2
  450. package/src/thirdparty/WeakSet.js +0 -27
  451. package/src/thirdparty/events-polyfills.js +0 -89
  452. package/src/thirdparty/fetch.js +0 -1
  453. package/src/thirdparty/template.js +0 -600
  454. package/src/util/CSSTransformUtils.js +0 -90
@@ -1,28 +1,51 @@
1
- import merge from "@ui5/webcomponents-utils/dist/sap/base/util/merge.js";
2
- import boot from "./boot.js";
3
- import { skipOriginalEvent } from "./config/NoConflict.js";
4
- import DOMObserver from "./compatibility/DOMObserver.js";
1
+ import merge from "./thirdparty/merge.js";
2
+ import { boot } from "./Boot.js";
5
3
  import UI5ElementMetadata from "./UI5ElementMetadata.js";
4
+ import EventProvider from "./EventProvider.js";
5
+ import getSingletonElementInstance from "./util/getSingletonElementInstance.js";
6
6
  import StaticAreaItem from "./StaticAreaItem.js";
7
- import Integer from "./types/Integer.js";
8
- import RenderScheduler from "./RenderScheduler.js";
9
- import { getConstructableStyle, createHeadStyle } from "./CSS.js";
10
- import { getEffectiveStyle } from "./Theming.js";
7
+ import updateShadowRoot from "./updateShadowRoot.js";
8
+ import { renderDeferred, renderImmediately, cancelRender } from "./Render.js";
9
+ import { registerTag, isTagRegistered, recordTagRegistrationFailure } from "./CustomElementsRegistry.js";
10
+ import { observeDOMNode, unobserveDOMNode } from "./DOMObserver.js";
11
+ import { skipOriginalEvent } from "./config/NoConflict.js";
12
+ import getEffectiveDir from "./locale/getEffectiveDir.js";
13
+ import DataType from "./types/DataType.js";
11
14
  import { kebabToCamelCase, camelToKebabCase } from "./util/StringHelper.js";
12
15
  import isValidPropertyName from "./util/isValidPropertyName.js";
16
+ import isDescendantOf from "./util/isDescendantOf.js";
17
+ import { isSlot, getSlotName, getSlottedElementsList } from "./util/SlotsHelper.js";
18
+ import arraysAreEqual from "./util/arraysAreEqual.js";
19
+ import getClassCopy from "./util/getClassCopy.js";
20
+ import { markAsRtlAware } from "./locale/RTLAwareRegistry.js";
21
+ import preloadLinks from "./theming/preloadLinks.js";
13
22
 
14
- const metadata = {
15
- events: {
16
- _propertyChange: {},
17
- },
18
- };
19
-
20
- const DefinitionsSet = new Set();
21
23
  let autoId = 0;
22
24
 
23
25
  const elementTimeouts = new Map();
26
+ const uniqueDependenciesCache = new Map();
27
+
28
+ /**
29
+ * Triggers re-rendering of a UI5Element instance due to state change.
30
+ *
31
+ * @param changeInfo An object with information about the change that caused invalidation.
32
+ * @private
33
+ */
34
+ function _invalidate(changeInfo) {
35
+ // Invalidation should be suppressed: 1) before the component is rendered for the first time 2) and during the execution of onBeforeRendering
36
+ // This is necessary not only as an optimization, but also to avoid infinite loops on invalidation between children and parents (when invalidateOnChildChange is used)
37
+ if (this._suppressInvalidation) {
38
+ return;
39
+ }
40
+
41
+ // Call the onInvalidation hook
42
+ this.onInvalidation(changeInfo);
43
+
44
+ this._changedState.push(changeInfo);
45
+ renderDeferred(this);
46
+ this._eventProvider.fireEvent("invalidate", { ...changeInfo, target: this });
47
+ }
24
48
 
25
- const GLOBAL_CONTENT_DENSITY_CSS_VAR = "--_ui5_content_density";
26
49
  /**
27
50
  * Base class for all UI5 Web Components
28
51
  *
@@ -36,56 +59,40 @@ const GLOBAL_CONTENT_DENSITY_CSS_VAR = "--_ui5_content_density";
36
59
  class UI5Element extends HTMLElement {
37
60
  constructor() {
38
61
  super();
39
- this._generateId();
40
- this._initializeState();
41
- this._upgradeAllProperties();
42
- this._initializeContainers();
43
- this._upToDate = false;
44
62
 
63
+ this._changedState = []; // Filled on each invalidation, cleared on re-render (used for debugging)
64
+ this._suppressInvalidation = true; // A flag telling whether all invalidations should be ignored. Initialized with "true" because a UI5Element can not be invalidated until it is rendered for the first time
65
+ this._inDOM = false; // A flag telling whether the UI5Element is currently in the DOM tree of the document or not
66
+ this._fullyConnected = false; // A flag telling whether the UI5Element's onEnterDOM hook was called (since it's possible to have the element removed from DOM before that)
67
+ this._childChangeListeners = new Map(); // used to store lazy listeners per slot for the child change event of every child inside that slot
68
+ this._slotChangeListeners = new Map(); // used to store lazy listeners per slot for the slotchange event of all slot children inside that slot
69
+ this._eventProvider = new EventProvider(); // used by parent components for listening to changes to child components
45
70
  let deferredResolve;
46
71
  this._domRefReadyPromise = new Promise(resolve => {
47
72
  deferredResolve = resolve;
48
73
  });
49
74
  this._domRefReadyPromise._deferredResolve = deferredResolve;
50
75
 
51
- this._monitoredChildProps = new Map();
52
- this._firePropertyChange = false;
53
- }
76
+ this._initializeState();
77
+ this._upgradeAllProperties();
54
78
 
55
- /**
56
- * @private
57
- */
58
- _generateId() {
59
- this._id = `ui5wc_${++autoId}`;
79
+ if (this.constructor._needsShadowDOM()) {
80
+ this.attachShadow({ mode: "open" });
81
+ }
60
82
  }
61
83
 
62
84
  /**
63
- * @private
85
+ * Returns a unique ID for this UI5 Element
86
+ *
87
+ * @deprecated - This property is not guaranteed in future releases
88
+ * @protected
64
89
  */
65
- _initializeContainers() {
66
- const needsShadowDOM = this.constructor._needsShadowDOM();
67
- const needsStaticArea = this.constructor._needsStaticArea();
68
-
69
- // Init Shadow Root
70
- if (needsShadowDOM) {
71
- this.attachShadow({ mode: "open" });
72
-
73
- // IE11, Edge
74
- if (window.ShadyDOM) {
75
- createHeadStyle(this.constructor);
76
- }
77
-
78
- // Chrome
79
- if (document.adoptedStyleSheets) {
80
- const style = getConstructableStyle(this.constructor);
81
- this.shadowRoot.adoptedStyleSheets = [style];
82
- }
90
+ get _id() {
91
+ if (!this.__id) {
92
+ this.__id = `ui5wc_${++autoId}`;
83
93
  }
84
94
 
85
- // Init StaticAreaItem only if needed
86
- if (needsStaticArea) {
87
- this.staticAreaItem = new StaticAreaItem(this);
88
- }
95
+ return this.__id;
89
96
  }
90
97
 
91
98
  /**
@@ -93,28 +100,30 @@ class UI5Element extends HTMLElement {
93
100
  * @private
94
101
  */
95
102
  async connectedCallback() {
96
- const needsShadowDOM = this.constructor._needsShadowDOM();
97
- const needsStaticArea = this.constructor._needsStaticArea();
103
+ this.setAttribute(this.constructor.getMetadata().getPureTag(), "");
104
+ if (this.constructor.getMetadata().supportsF6FastNavigation()) {
105
+ this.setAttribute("data-sap-ui-fastnavgroup", "true");
106
+ }
107
+
98
108
  const slotsAreManaged = this.constructor.getMetadata().slotsAreManaged();
99
109
 
100
- // Render the Shadow DOM
101
- if (needsShadowDOM) {
102
- if (slotsAreManaged) {
103
- // always register the observer before yielding control to the main thread (await)
104
- this._startObservingDOMChildren();
105
- await this._processChildren();
106
- }
110
+ this._inDOM = true;
107
111
 
108
- await RenderScheduler.renderImmediately(this);
109
- this._domRefReadyPromise._deferredResolve();
110
- if (typeof this.onEnterDOM === "function") {
111
- this.onEnterDOM();
112
- }
112
+ if (slotsAreManaged) {
113
+ // always register the observer before yielding control to the main thread (await)
114
+ this._startObservingDOMChildren();
115
+ await this._processChildren();
113
116
  }
114
117
 
115
- // Render Fragment if neccessary
116
- if (needsStaticArea) {
117
- this.staticAreaItem._updateFragment(this);
118
+ if (!this._inDOM) { // Component removed from DOM while _processChildren was running
119
+ return;
120
+ }
121
+
122
+ renderImmediately(this);
123
+ this._domRefReadyPromise._deferredResolve();
124
+ this._fullyConnected = true;
125
+ if (typeof this.onEnterDOM === "function") {
126
+ this.onEnterDOM();
118
127
  }
119
128
  }
120
129
 
@@ -123,23 +132,26 @@ class UI5Element extends HTMLElement {
123
132
  * @private
124
133
  */
125
134
  disconnectedCallback() {
126
- const needsShadowDOM = this.constructor._needsShadowDOM();
127
- const needsStaticArea = this.constructor._needsStaticArea();
128
135
  const slotsAreManaged = this.constructor.getMetadata().slotsAreManaged();
129
136
 
130
- if (needsShadowDOM) {
131
- if (slotsAreManaged) {
132
- this._stopObservingDOMChildren();
133
- }
137
+ this._inDOM = false;
134
138
 
139
+ if (slotsAreManaged) {
140
+ this._stopObservingDOMChildren();
141
+ }
142
+
143
+ if (this._fullyConnected) {
135
144
  if (typeof this.onExitDOM === "function") {
136
145
  this.onExitDOM();
137
146
  }
147
+ this._fullyConnected = false;
138
148
  }
139
149
 
140
- if (needsStaticArea) {
141
- this.staticAreaItem._removeFragmentFromStaticArea();
150
+ if (this.staticAreaItem && this.staticAreaItem.parentElement) {
151
+ this.staticAreaItem.parentElement.removeChild(this.staticAreaItem);
142
152
  }
153
+
154
+ cancelRender(this);
143
155
  }
144
156
 
145
157
  /**
@@ -150,19 +162,21 @@ class UI5Element extends HTMLElement {
150
162
  if (!shouldObserveChildren) {
151
163
  return;
152
164
  }
165
+
166
+ const canSlotText = this.constructor.getMetadata().canSlotText();
153
167
  const mutationObserverOptions = {
154
168
  childList: true,
155
- subtree: true,
156
- characterData: true,
169
+ subtree: canSlotText,
170
+ characterData: canSlotText,
157
171
  };
158
- DOMObserver.observeDOMNode(this, this._processChildren.bind(this), mutationObserverOptions);
172
+ observeDOMNode(this, this._processChildren.bind(this), mutationObserverOptions);
159
173
  }
160
174
 
161
175
  /**
162
176
  * @private
163
177
  */
164
178
  _stopObservingDOMChildren() {
165
- DOMObserver.unobserveDOMNode(this);
179
+ unobserveDOMNode(this);
166
180
  }
167
181
 
168
182
  /**
@@ -181,11 +195,17 @@ class UI5Element extends HTMLElement {
181
195
  */
182
196
  async _updateSlots() {
183
197
  const slotsMap = this.constructor.getMetadata().getSlots();
184
- const canSlotText = slotsMap.default && slotsMap.default.type === Node;
198
+ const canSlotText = this.constructor.getMetadata().canSlotText();
185
199
  const domChildren = Array.from(canSlotText ? this.childNodes : this.children);
186
200
 
187
- // Init the _state object based on the supported slots
201
+ const slotsCachedContentMap = new Map(); // Store here the content of each slot before the mutation occurred
202
+ const propertyNameToSlotMap = new Map(); // Used for reverse lookup to determine to which slot the property name corresponds
203
+
204
+ // Init the _state object based on the supported slots and store the previous values
188
205
  for (const [slotName, slotData] of Object.entries(slotsMap)) { // eslint-disable-line
206
+ const propertyName = slotData.propertyName || slotName;
207
+ propertyNameToSlotMap.set(propertyName, slotName);
208
+ slotsCachedContentMap.set(propertyName, [...this._state[propertyName]]);
189
209
  this._clearSlot(slotName, slotData);
190
210
  }
191
211
 
@@ -194,7 +214,7 @@ class UI5Element extends HTMLElement {
194
214
 
195
215
  const allChildrenUpgraded = domChildren.map(async (child, idx) => {
196
216
  // Determine the type of the child (mainly by the slot attribute)
197
- const slotName = this.constructor._getSlotName(child);
217
+ const slotName = getSlotName(child);
198
218
  const slotData = slotsMap[slotName];
199
219
 
200
220
  // Check if the slotName is supported
@@ -232,8 +252,15 @@ class UI5Element extends HTMLElement {
232
252
 
233
253
  child = this.constructor.getMetadata().constructor.validateSlotValue(child, slotData);
234
254
 
235
- if (child.isUI5Element && slotData.listenFor) {
236
- this._attachChildPropertyUpdated(child, slotData.listenFor);
255
+ // Listen for any invalidation on the child if invalidateOnChildChange is true or an object (ignore when false or not set)
256
+ if (child.isUI5Element && slotData.invalidateOnChildChange) {
257
+ const method = (child.attachInvalidate || child._attachChange).bind(child);
258
+ method(this._getChildChangeListener(slotName));
259
+ }
260
+
261
+ // Listen for the slotchange event if the child is a slot itself
262
+ if (isSlot(child)) {
263
+ this._attachSlotChange(child, slotName);
237
264
  }
238
265
 
239
266
  const propertyName = slotData.propertyName || slotName;
@@ -249,10 +276,33 @@ class UI5Element extends HTMLElement {
249
276
 
250
277
  // Distribute the child in the _state object, keeping the Light DOM order,
251
278
  // not the order elements are defined.
252
- slottedChildrenMap.forEach((children, slot) => {
253
- this._state[slot] = children.sort((a, b) => a.idx - b.idx).map(_ => _.child);
279
+ slottedChildrenMap.forEach((children, propertyName) => {
280
+ this._state[propertyName] = children.sort((a, b) => a.idx - b.idx).map(_ => _.child);
254
281
  });
255
- this._invalidate();
282
+
283
+ // Compare the content of each slot with the cached values and invalidate for the ones that changed
284
+ let invalidated = false;
285
+ for (const [slotName, slotData] of Object.entries(slotsMap)) { // eslint-disable-line
286
+ const propertyName = slotData.propertyName || slotName;
287
+ if (!arraysAreEqual(slotsCachedContentMap.get(propertyName), this._state[propertyName])) {
288
+ _invalidate.call(this, {
289
+ type: "slot",
290
+ name: propertyNameToSlotMap.get(propertyName),
291
+ reason: "children",
292
+ });
293
+ invalidated = true;
294
+ }
295
+ }
296
+
297
+ // If none of the slots had an invalidation due to changes to immediate children,
298
+ // the change is considered to be text content of the default slot
299
+ if (!invalidated) {
300
+ _invalidate.call(this, {
301
+ type: "slot",
302
+ name: "default",
303
+ reason: "textcontent",
304
+ });
305
+ }
256
306
  }
257
307
 
258
308
  /**
@@ -261,20 +311,62 @@ class UI5Element extends HTMLElement {
261
311
  */
262
312
  _clearSlot(slotName, slotData) {
263
313
  const propertyName = slotData.propertyName || slotName;
264
-
265
- let children = this._state[propertyName];
266
- if (!Array.isArray(children)) {
267
- children = [children];
268
- }
314
+ const children = this._state[propertyName];
269
315
 
270
316
  children.forEach(child => {
271
317
  if (child && child.isUI5Element) {
272
- this._detachChildPropertyUpdated(child);
318
+ const method = (child.detachInvalidate || child._detachChange).bind(child);
319
+ method(this._getChildChangeListener(slotName));
320
+ }
321
+
322
+ if (isSlot(child)) {
323
+ this._detachSlotChange(child, slotName);
273
324
  }
274
325
  });
275
326
 
276
327
  this._state[propertyName] = [];
277
- this._invalidate(propertyName, []);
328
+ }
329
+
330
+ /**
331
+ * Attach a callback that will be executed whenever the component is invalidated
332
+ *
333
+ * @param callback
334
+ * @public
335
+ */
336
+ attachInvalidate(callback) {
337
+ this._eventProvider.attachEvent("invalidate", callback);
338
+ }
339
+
340
+ /**
341
+ * Detach the callback that is executed whenever the component is invalidated
342
+ *
343
+ * @param callback
344
+ * @public
345
+ */
346
+ detachInvalidate(callback) {
347
+ this._eventProvider.detachEvent("invalidate", callback);
348
+ }
349
+
350
+ /**
351
+ * Callback that is executed whenever a monitored child changes its state
352
+ *
353
+ * @param slotName the slot in which a child was invalidated
354
+ * @param childChangeInfo the changeInfo object for the child in the given slot
355
+ * @private
356
+ */
357
+ _onChildChange(slotName, childChangeInfo) {
358
+ if (!this.constructor.getMetadata().shouldInvalidateOnChildChange(slotName, childChangeInfo.type, childChangeInfo.name)) {
359
+ return;
360
+ }
361
+
362
+ // The component should be invalidated as this type of change on the child is listened for
363
+ // However, no matter what changed on the child (property/slot), the invalidation is registered as "type=slot" for the component itself
364
+ _invalidate.call(this, {
365
+ type: "slot",
366
+ name: slotName,
367
+ reason: "childchange",
368
+ child: childChangeInfo.target,
369
+ });
278
370
  }
279
371
 
280
372
  /**
@@ -289,9 +381,8 @@ class UI5Element extends HTMLElement {
289
381
  const propertyTypeClass = properties[nameInCamelCase].type;
290
382
  if (propertyTypeClass === Boolean) {
291
383
  newValue = newValue !== null;
292
- }
293
- if (propertyTypeClass === Integer) {
294
- newValue = parseInt(newValue);
384
+ } else if (isDescendantOf(propertyTypeClass, DataType)) {
385
+ newValue = propertyTypeClass.attributeToProperty(newValue);
295
386
  }
296
387
  this[nameInCamelCase] = newValue;
297
388
  }
@@ -304,22 +395,24 @@ class UI5Element extends HTMLElement {
304
395
  if (!this.constructor.getMetadata().hasAttribute(name)) {
305
396
  return;
306
397
  }
307
-
308
- if (typeof newValue === "object") {
309
- return;
310
- }
311
-
398
+ const properties = this.constructor.getMetadata().getProperties();
399
+ const propertyTypeClass = properties[name].type;
312
400
  const attrName = camelToKebabCase(name);
313
401
  const attrValue = this.getAttribute(attrName);
314
- if (typeof newValue === "boolean") {
402
+
403
+ if (propertyTypeClass === Boolean) {
315
404
  if (newValue === true && attrValue === null) {
316
405
  this.setAttribute(attrName, "");
317
406
  } else if (newValue === false && attrValue !== null) {
318
407
  this.removeAttribute(attrName);
319
408
  }
320
- } else if (attrValue !== newValue) {
321
- this.setAttribute(attrName, newValue);
322
- }
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
323
416
  }
324
417
 
325
418
  /**
@@ -345,101 +438,96 @@ class UI5Element extends HTMLElement {
345
438
  * @private
346
439
  */
347
440
  _initializeState() {
348
- const defaultState = this.constructor._getDefaultState();
349
- this._state = Object.assign({}, defaultState);
441
+ this._state = { ...this.constructor.getMetadata().getInitialState() };
350
442
  }
351
443
 
352
444
  /**
445
+ * Returns a singleton event listener for the "change" event of a child in a given slot
446
+ *
447
+ * @param slotName the name of the slot, where the child is
448
+ * @returns {any}
353
449
  * @private
354
450
  */
355
- _attachChildPropertyUpdated(child, listenFor) {
356
- const childMetadata = child.constructor.getMetadata(),
357
- slotName = this.constructor._getSlotName(child), // all slotted children have the same configuration
358
- childProperties = childMetadata.getProperties();
359
-
360
- let observedProps = [],
361
- notObservedProps = [];
362
-
363
- if (Array.isArray(listenFor)) {
364
- observedProps = listenFor;
365
- } else {
366
- observedProps = Array.isArray(listenFor.props) ? listenFor.props : Object.keys(childProperties);
367
- notObservedProps = Array.isArray(listenFor.exclude) ? listenFor.exclude : [];
368
- }
369
-
370
- if (!this._monitoredChildProps.has(slotName)) {
371
- this._monitoredChildProps.set(slotName, { observedProps, notObservedProps });
451
+ _getChildChangeListener(slotName) {
452
+ if (!this._childChangeListeners.has(slotName)) {
453
+ this._childChangeListeners.set(slotName, this._onChildChange.bind(this, slotName));
372
454
  }
373
-
374
- child.addEventListener("_propertyChange", this._invalidateParentOnPropertyUpdate);
375
- child._firePropertyChange = true;
455
+ return this._childChangeListeners.get(slotName);
376
456
  }
377
457
 
378
458
  /**
459
+ * Returns a singleton slotchange event listener that invalidates the component due to changes in the given slot
460
+ *
461
+ * @param slotName the name of the slot, where the slot element (whose slotchange event we're listening to) is
462
+ * @returns {any}
379
463
  * @private
380
464
  */
381
- _detachChildPropertyUpdated(child) {
382
- child.removeEventListener("_propertyChange", this._invalidateParentOnPropertyUpdate);
383
- child._firePropertyChange = false;
465
+ _getSlotChangeListener(slotName) {
466
+ if (!this._slotChangeListeners.has(slotName)) {
467
+ this._slotChangeListeners.set(slotName, this._onSlotChange.bind(this, slotName));
468
+ }
469
+ return this._slotChangeListeners.get(slotName);
384
470
  }
385
471
 
386
472
  /**
387
473
  * @private
388
474
  */
389
- _propertyChange(name, value) {
390
- this._updateAttribute(name, value);
391
-
392
- if (this._firePropertyChange) {
393
- this.dispatchEvent(new CustomEvent("_propertyChange", {
394
- detail: { name, newValue: value },
395
- composed: false,
396
- bubbles: true,
397
- }));
398
- }
475
+ _attachSlotChange(child, slotName) {
476
+ child.addEventListener("slotchange", this._getSlotChangeListener(slotName));
399
477
  }
400
478
 
401
479
  /**
402
480
  * @private
403
481
  */
404
- _invalidateParentOnPropertyUpdate(prop) {
405
- // The web component to be invalidated
406
- const parentNode = this.parentNode;
407
- if (!parentNode) {
408
- return;
409
- }
410
-
411
- const slotName = parentNode.constructor._getSlotName(this);
412
- const propsMetadata = parentNode._monitoredChildProps.get(slotName);
413
-
414
- if (!propsMetadata) {
415
- return;
416
- }
417
- const { observedProps, notObservedProps } = propsMetadata;
418
-
419
- if (observedProps.includes(prop.detail.name) && !notObservedProps.includes(prop.detail.name)) {
420
- parentNode._invalidate("_parent_", this);
421
- }
482
+ _detachSlotChange(child, slotName) {
483
+ child.removeEventListener("slotchange", this._getSlotChangeListener(slotName));
422
484
  }
423
485
 
424
486
  /**
425
- * Asynchronously re-renders an already rendered web component
487
+ * Whenever a slot element is slotted inside a UI5 Web Component, its slotchange event invalidates the component
488
+ *
489
+ * @param slotName the name of the slot, where the slot element (whose slotchange event we're listening to) is
426
490
  * @private
427
491
  */
428
- _invalidate() {
429
- if (!this._upToDate) {
430
- // console.log("already invalidated", this, ...arguments);
431
- return;
432
- }
433
-
434
- if (this.getDomRef() && !this._suppressInvalidation) {
435
- this._upToDate = false;
436
- // console.log("INVAL", this, ...arguments);
437
- RenderScheduler.renderDeferred(this);
438
- }
492
+ _onSlotChange(slotName) {
493
+ _invalidate.call(this, {
494
+ type: "slot",
495
+ name: slotName,
496
+ reason: "slotchange",
497
+ });
439
498
  }
440
499
 
441
500
  /**
442
- * Do not call this method directly, only intended to be called by RenderScheduler.js
501
+ * A callback that is executed each time an already rendered component is invalidated (scheduled for re-rendering)
502
+ *
503
+ * @param changeInfo An object with information about the change that caused invalidation.
504
+ * The object can have the following properties:
505
+ * - type: (property|slot) tells what caused the invalidation
506
+ * 1) property: a property value was changed either directly or as a result of changing the corresponding attribute
507
+ * 2) slot: a slotted node(nodes) changed in one of several ways (see "reason")
508
+ *
509
+ * - name: the name of the property or slot that caused the invalidation
510
+ *
511
+ * - reason: (children|textcontent|childchange|slotchange) relevant only for type="slot" only and tells exactly what changed in the slot
512
+ * 1) children: immediate children (HTML elements or text nodes) were added, removed or reordered in the slot
513
+ * 2) textcontent: text nodes in the slot changed value (or nested text nodes were added or changed value). Can only trigger for slots of "type: Node"
514
+ * 3) slotchange: a slot element, slotted inside that slot had its "slotchange" event listener called. This practically means that transitively slotted children changed.
515
+ * Can only trigger if the child of a slot is a slot element itself.
516
+ * 4) childchange: indicates that a UI5Element child in that slot was invalidated and in turn invalidated the component.
517
+ * Can only trigger for slots with "invalidateOnChildChange" metadata descriptor
518
+ *
519
+ * - newValue: the new value of the property (for type="property" only)
520
+ *
521
+ * - oldValue: the old value of the property (for type="property" only)
522
+ *
523
+ * - child the child that was changed (for type="slot" and reason="childchange" only)
524
+ *
525
+ * @public
526
+ */
527
+ onInvalidation(changeInfo) {}
528
+
529
+ /**
530
+ * Do not call this method directly, only intended to be called by js
443
531
  * @protected
444
532
  */
445
533
  _render() {
@@ -458,15 +546,37 @@ class UI5Element extends HTMLElement {
458
546
  }
459
547
 
460
548
  // resume normal invalidation handling
461
- delete this._suppressInvalidation;
549
+ this._suppressInvalidation = false;
462
550
 
463
551
  // Update the shadow root with the render result
464
- // console.log(this.getDomRef() ? "RE-RENDER" : "FIRST RENDER", this);
465
- this._upToDate = true;
466
- this._updateShadowRoot();
552
+ /*
553
+ if (this._changedState.length) {
554
+ let element = this.localName;
555
+ if (this.id) {
556
+ element = `${element}#${this.id}`;
557
+ }
558
+ console.log("Re-rendering:", element, this._changedState.map(x => { // eslint-disable-line
559
+ let res = `${x.type}`;
560
+ if (x.reason) {
561
+ res = `${res}(${x.reason})`;
562
+ }
563
+ res = `${res}: ${x.name}`;
564
+ if (x.type === "property") {
565
+ res = `${res} ${x.oldValue} => ${x.newValue}`;
566
+ }
567
+
568
+ return res;
569
+ }));
570
+ }
571
+ */
572
+ this._changedState = [];
467
573
 
468
- if (this.constructor._needsStaticArea()) {
469
- this.staticAreaItem._updateFragment(this);
574
+ // Update shadow root and static area item
575
+ if (this.constructor._needsShadowDOM()) {
576
+ updateShadowRoot(this);
577
+ }
578
+ if (this.staticAreaItem) {
579
+ this.staticAreaItem.update();
470
580
  }
471
581
 
472
582
  // Safari requires that children get the slot attribute only after the slot tags have been rendered in the shadow DOM
@@ -480,19 +590,6 @@ class UI5Element extends HTMLElement {
480
590
  }
481
591
  }
482
592
 
483
- /**
484
- * @private
485
- */
486
- _updateShadowRoot() {
487
- let styleToPrepend;
488
- const renderResult = this.constructor.template(this);
489
-
490
- if (!document.adoptedStyleSheets && !window.ShadyDOM) {
491
- styleToPrepend = getEffectiveStyle(this.constructor);
492
- }
493
- this.constructor.render(renderResult, this.shadowRoot, styleToPrepend, { eventContext: this });
494
- }
495
-
496
593
  /**
497
594
  * @private
498
595
  */
@@ -515,16 +612,27 @@ class UI5Element extends HTMLElement {
515
612
 
516
613
  /**
517
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
518
616
  * Use this method instead of "this.shadowRoot" to read the Shadow DOM, if ever necessary
617
+ *
519
618
  * @public
520
619
  */
521
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
+
522
626
  if (!this.shadowRoot || this.shadowRoot.children.length === 0) {
523
627
  return;
524
628
  }
525
629
 
526
- return this.shadowRoot.children.length === 1
527
- ? this.shadowRoot.children[0] : this.shadowRoot.children[1];
630
+ const children = [...this.shadowRoot.children].filter(child => !["link", "style"].includes(child.localName));
631
+ if (children.length !== 1) {
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
633
+ }
634
+
635
+ return children[0];
528
636
  }
529
637
 
530
638
  /**
@@ -540,6 +648,16 @@ class UI5Element extends HTMLElement {
540
648
  }
541
649
  }
542
650
 
651
+ /**
652
+ * Waits for dom ref and then returns the DOM Element marked with "data-sap-focus-ref" inside the template.
653
+ * This is the element that will receive the focus by default.
654
+ * @public
655
+ */
656
+ async getFocusDomRefAsync() {
657
+ await this._waitForDomRef();
658
+ return this.getFocusDomRef();
659
+ }
660
+
543
661
  /**
544
662
  * Set the focus to the element, returned by "getFocusDomRef()" (marked by "data-sap-focus-ref")
545
663
  * @public
@@ -560,37 +678,47 @@ class UI5Element extends HTMLElement {
560
678
  * @param name - name of the event
561
679
  * @param data - additional data for the event
562
680
  * @param cancelable - true, if the user can call preventDefault on the event object
681
+ * @param bubbles - true, if the event bubbles
563
682
  * @returns {boolean} false, if the event was cancelled (preventDefault called), true otherwise
564
683
  */
565
- fireEvent(name, data, cancelable) {
566
- let compatEventResult = true; // Initialized to true, because if the event is not fired at all, it should be considered "not-prevented"
684
+ fireEvent(name, data, cancelable = false, bubbles = true) {
685
+ const eventResult = this._fireEvent(name, data, cancelable, bubbles);
686
+ const camelCaseEventName = kebabToCamelCase(name);
687
+
688
+ if (camelCaseEventName !== name) {
689
+ return eventResult && this._fireEvent(camelCaseEventName, data, cancelable);
690
+ }
567
691
 
692
+ return eventResult;
693
+ }
694
+
695
+ _fireEvent(name, data, cancelable = false, bubbles = true) {
568
696
  const noConflictEvent = new CustomEvent(`ui5-${name}`, {
569
697
  detail: data,
570
698
  composed: false,
571
- bubbles: true,
699
+ bubbles,
572
700
  cancelable,
573
701
  });
574
702
 
575
- // This will be false if the compat event is prevented
576
- compatEventResult = this.dispatchEvent(noConflictEvent);
703
+ // This will be false if the no-conflict event is prevented
704
+ const noConflictEventResult = this.dispatchEvent(noConflictEvent);
577
705
 
578
706
  if (skipOriginalEvent(name)) {
579
- return compatEventResult;
707
+ return noConflictEventResult;
580
708
  }
581
709
 
582
- const customEvent = new CustomEvent(name, {
710
+ const normalEvent = new CustomEvent(name, {
583
711
  detail: data,
584
712
  composed: false,
585
- bubbles: true,
713
+ bubbles,
586
714
  cancelable,
587
715
  });
588
716
 
589
717
  // This will be false if the normal event is prevented
590
- const normalEventResult = this.dispatchEvent(customEvent);
718
+ const normalEventResult = this.dispatchEvent(normalEvent);
591
719
 
592
720
  // Return false if any of the two events was prevented (its result was false).
593
- return normalEventResult && compatEventResult;
721
+ return normalEventResult && noConflictEventResult;
594
722
  }
595
723
 
596
724
  /**
@@ -599,24 +727,19 @@ class UI5Element extends HTMLElement {
599
727
  * @public
600
728
  */
601
729
  getSlottedNodes(slotName) {
602
- const reducer = (acc, curr) => {
603
- if (curr.localName !== "slot") {
604
- return acc.concat([curr]);
605
- }
606
- return acc.concat(curr.assignedNodes({ flatten: true }).filter(item => item instanceof HTMLElement));
607
- };
608
-
609
- return this[slotName].reduce(reducer, []);
610
- }
611
-
612
- get isCompact() {
613
- return getComputedStyle(this).getPropertyValue(GLOBAL_CONTENT_DENSITY_CSS_VAR) === "compact";
730
+ return getSlottedElementsList(this[slotName]);
614
731
  }
615
732
 
616
- updateStaticAreaItemContentDensity() {
617
- if (this.staticAreaItem) {
618
- this.staticAreaItem._updateContentDensity(this.isCompact);
619
- }
733
+ /**
734
+ * Determines whether the component should be rendered in RTL mode or not.
735
+ * Returns: "rtl", "ltr" or undefined
736
+ *
737
+ * @public
738
+ * @returns {String|undefined}
739
+ */
740
+ get effectiveDir() {
741
+ markAsRtlAware(this.constructor); // if a UI5 Element calls this method, it's considered to be rtl-aware
742
+ return getEffectiveDir(this);
620
743
  }
621
744
 
622
745
  /**
@@ -636,26 +759,6 @@ class UI5Element extends HTMLElement {
636
759
  return this.getMetadata().getAttributesList();
637
760
  }
638
761
 
639
- /**
640
- * @private
641
- */
642
- static _getSlotName(child) {
643
- // Text nodes can only go to the default slot
644
- if (!(child instanceof HTMLElement)) {
645
- return "default";
646
- }
647
-
648
- // Discover the slot based on the real slot name (f.e. footer => footer, or content-32 => content)
649
- const slot = child.getAttribute("slot");
650
- if (slot) {
651
- const match = slot.match(/^(.+?)-\d+$/);
652
- return match ? match[1] : slot;
653
- }
654
-
655
- // Use default slot as a fallback
656
- return "default";
657
- }
658
-
659
762
  /**
660
763
  * @private
661
764
  */
@@ -667,62 +770,26 @@ class UI5Element extends HTMLElement {
667
770
  * @private
668
771
  */
669
772
  static _needsStaticArea() {
670
- return typeof this.staticAreaTemplate === "function";
773
+ return !!this.staticAreaTemplate;
671
774
  }
672
775
 
673
776
  /**
674
777
  * @public
675
778
  */
676
779
  getStaticAreaItemDomRef() {
677
- return this.staticAreaItem.getDomRef();
678
- }
679
-
680
- /**
681
- * @private
682
- */
683
- static _getDefaultState() {
684
- if (this._defaultState) {
685
- return this._defaultState;
780
+ if (!this.constructor._needsStaticArea()) {
781
+ throw new Error("This component does not use the static area");
686
782
  }
687
783
 
688
- const MetadataClass = this.getMetadata();
689
- const defaultState = {};
690
- const slotsAreManaged = MetadataClass.slotsAreManaged();
691
-
692
- // Initialize properties
693
- const props = MetadataClass.getProperties();
694
- for (const propName in props) { // eslint-disable-line
695
- const propType = props[propName].type;
696
- const propDefaultValue = props[propName].defaultValue;
697
-
698
- if (propType === Boolean) {
699
- defaultState[propName] = false;
700
-
701
- if (propDefaultValue !== undefined) {
702
- console.warn("The 'defaultValue' metadata key is ignored for all booleans properties, they would be initialized with 'false' by default"); // eslint-disable-line
703
- }
704
- } else if (props[propName].multiple) {
705
- defaultState[propName] = [];
706
- } else if (propType === Object) {
707
- defaultState[propName] = "defaultValue" in props[propName] ? props[propName].defaultValue : {};
708
- } else if (propType === String) {
709
- defaultState[propName] = "defaultValue" in props[propName] ? props[propName].defaultValue : "";
710
- } else {
711
- defaultState[propName] = propDefaultValue;
712
- }
784
+ if (!this.staticAreaItem) {
785
+ this.staticAreaItem = StaticAreaItem.createInstance();
786
+ this.staticAreaItem.setOwnerElement(this);
713
787
  }
714
-
715
- // Initialize slots
716
- if (slotsAreManaged) {
717
- const slots = MetadataClass.getSlots();
718
- for (const [slotName, slotData] of Object.entries(slots)) { // eslint-disable-line
719
- const propertyName = slotData.propertyName || slotName;
720
- defaultState[propertyName] = [];
721
- }
788
+ if (!this.staticAreaItem.parentElement) {
789
+ getSingletonElementInstance("ui5-static-area").appendChild(this.staticAreaItem);
722
790
  }
723
791
 
724
- this._defaultState = defaultState;
725
- return defaultState;
792
+ return this.staticAreaItem.getDomRef();
726
793
  }
727
794
 
728
795
  /**
@@ -736,13 +803,25 @@ class UI5Element extends HTMLElement {
736
803
  const properties = this.getMetadata().getProperties();
737
804
  for (const [prop, propData] of Object.entries(properties)) { // eslint-disable-line
738
805
  if (!isValidPropertyName(prop)) {
739
- throw new Error(`"${prop}" is not a valid property name. Use a name that does not collide with DOM APIs`);
806
+ console.warn(`"${prop}" is not a valid property name. Use a name that does not collide with DOM APIs`); /* eslint-disable-line */
740
807
  }
741
808
 
742
- if (propData.type === "boolean" && propData.defaultValue) {
809
+ if (propData.type === Boolean && propData.defaultValue) {
743
810
  throw new Error(`Cannot set a default value for property "${prop}". All booleans are false by default.`);
744
811
  }
745
812
 
813
+ if (propData.type === Array) {
814
+ throw new Error(`Wrong type for property "${prop}". Properties cannot be of type Array - use "multiple: true" and set "type" to the single value type, such as "String", "Object", etc...`);
815
+ }
816
+
817
+ if (propData.type === Object && propData.defaultValue) {
818
+ throw new Error(`Cannot set a default value for property "${prop}". All properties of type "Object" are empty objects by default.`);
819
+ }
820
+
821
+ if (propData.multiple && propData.defaultValue) {
822
+ throw new Error(`Cannot set a default value for property "${prop}". All multiple properties are empty arrays by default.`);
823
+ }
824
+
746
825
  Object.defineProperty(proto, prop, {
747
826
  get() {
748
827
  if (this._state[prop] !== undefined) {
@@ -762,14 +841,27 @@ class UI5Element extends HTMLElement {
762
841
  }
763
842
  },
764
843
  set(value) {
844
+ let isDifferent;
765
845
  value = this.constructor.getMetadata().constructor.validatePropertyValue(value, propData);
766
846
 
767
847
  const oldState = this._state[prop];
848
+ if (propData.multiple && propData.compareValues) {
849
+ isDifferent = !arraysAreEqual(oldState, value);
850
+ } else if (isDescendantOf(propData.type, DataType)) {
851
+ isDifferent = !propData.type.valuesAreEqual(oldState, value);
852
+ } else {
853
+ isDifferent = oldState !== value;
854
+ }
768
855
 
769
- if (oldState !== value) {
856
+ if (isDifferent) {
770
857
  this._state[prop] = value;
771
- this._invalidate(prop, value);
772
- this._propertyChange(prop, value);
858
+ _invalidate.call(this, {
859
+ type: "property",
860
+ name: prop,
861
+ newValue: value,
862
+ oldValue: oldState,
863
+ });
864
+ this._updateAttribute(prop, value);
773
865
  }
774
866
  },
775
867
  });
@@ -780,7 +872,7 @@ class UI5Element extends HTMLElement {
780
872
  const slots = this.getMetadata().getSlots();
781
873
  for (const [slotName, slotData] of Object.entries(slots)) { // eslint-disable-line
782
874
  if (!isValidPropertyName(slotName)) {
783
- throw new Error(`"${slotName}" is not a valid property name. Use a name that does not collide with DOM APIs`);
875
+ console.warn(`"${slotName}" is not a valid property name. Use a name that does not collide with DOM APIs`); /* eslint-disable-line */
784
876
  }
785
877
 
786
878
  const propertyName = slotData.propertyName || slotName;
@@ -792,7 +884,7 @@ class UI5Element extends HTMLElement {
792
884
  return [];
793
885
  },
794
886
  set() {
795
- throw new Error("Cannot set slots directly, use the DOM APIs");
887
+ throw new Error("Cannot set slot content directly, use the DOM APIs (appendChild, removeChild, etc...)");
796
888
  },
797
889
  });
798
890
  }
@@ -804,7 +896,7 @@ class UI5Element extends HTMLElement {
804
896
  * @protected
805
897
  */
806
898
  static get metadata() {
807
- return metadata;
899
+ return {};
808
900
  }
809
901
 
810
902
  /**
@@ -815,6 +907,58 @@ class UI5Element extends HTMLElement {
815
907
  return "";
816
908
  }
817
909
 
910
+ /**
911
+ * Returns the Static Area CSS for this UI5 Web Component Class
912
+ * @protected
913
+ */
914
+ static get staticAreaStyles() {
915
+ return "";
916
+ }
917
+
918
+ /**
919
+ * Returns an array with the dependencies for this UI5 Web Component, which could be:
920
+ * - composed components (used in its shadow root or static area item)
921
+ * - slotted components that the component may need to communicate with
922
+ *
923
+ * @protected
924
+ */
925
+ static get dependencies() {
926
+ return [];
927
+ }
928
+
929
+ /**
930
+ * Returns a list of the unique dependencies for this UI5 Web Component
931
+ *
932
+ * @public
933
+ */
934
+ static getUniqueDependencies() {
935
+ if (!uniqueDependenciesCache.has(this)) {
936
+ const filtered = this.dependencies.filter((dep, index, deps) => deps.indexOf(dep) === index);
937
+ uniqueDependenciesCache.set(this, filtered);
938
+ }
939
+
940
+ return uniqueDependenciesCache.get(this);
941
+ }
942
+
943
+ /**
944
+ * Returns a promise that resolves whenever all dependencies for this UI5 Web Component have resolved
945
+ *
946
+ * @returns {Promise<any[]>}
947
+ */
948
+ static whenDependenciesDefined() {
949
+ return Promise.all(this.getUniqueDependencies().map(dep => dep.define()));
950
+ }
951
+
952
+ /**
953
+ * Hook that will be called upon custom element definition
954
+ *
955
+ * @protected
956
+ * @returns {Promise<void>}
957
+ */
958
+ static async onDefine() {
959
+ return Promise.resolve();
960
+ }
961
+
818
962
  /**
819
963
  * Registers a UI5 Web Component in the browser window object
820
964
  * @public
@@ -823,21 +967,31 @@ class UI5Element extends HTMLElement {
823
967
  static async define() {
824
968
  await boot();
825
969
 
826
- if (this.onDefine) {
827
- await this.onDefine();
828
- }
970
+ await Promise.all([
971
+ this.whenDependenciesDefined(),
972
+ this.onDefine(),
973
+ ]);
829
974
 
830
975
  const tag = this.getMetadata().getTag();
976
+ const altTag = this.getMetadata().getAltTag();
831
977
 
832
- const definedLocally = DefinitionsSet.has(tag);
978
+ const definedLocally = isTagRegistered(tag);
833
979
  const definedGlobally = customElements.get(tag);
834
980
 
835
981
  if (definedGlobally && !definedLocally) {
836
- console.warn(`Skipping definition of tag ${tag}, because it was already defined by another instance of ui5-webcomponents.`); // eslint-disable-line
982
+ recordTagRegistrationFailure(tag);
837
983
  } else if (!definedGlobally) {
838
984
  this._generateAccessors();
839
- DefinitionsSet.add(tag);
985
+ registerTag(tag);
840
986
  window.customElements.define(tag, this);
987
+ preloadLinks(this);
988
+
989
+ if (altTag && !customElements.get(altTag)) {
990
+ registerTag(altTag);
991
+ window.customElements.define(altTag, getClassCopy(this, () => {
992
+ console.log(`The ${altTag} tag is deprecated and will be removed in the next release, please use ${tag} instead.`); // eslint-disable-line
993
+ }));
994
+ }
841
995
  }
842
996
  return this;
843
997
  }