@ui5/webcomponents-base 0.0.0-e463d2345 → 0.0.0-e58530409

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