@ui5/webcomponents-base 0.0.0-5f8ce9393 → 0.0.0-6cb3eb0db

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