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

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 (209) hide show
  1. package/.eslintignore +3 -1
  2. package/CHANGELOG.md +280 -0
  3. package/README.md +53 -7
  4. package/bundle.esm.js +13 -11
  5. package/dist/Boot.js +34 -18
  6. package/dist/CSP.js +59 -0
  7. package/dist/CustomElementsRegistry.js +60 -4
  8. package/dist/CustomElementsScope.js +20 -98
  9. package/dist/CustomElementsScopeUtils.js +108 -0
  10. package/dist/Device.js +22 -1
  11. package/dist/EventProvider.js +19 -25
  12. package/dist/FeaturesRegistry.js +4 -1
  13. package/dist/FontFace.js +7 -95
  14. package/dist/InitialConfiguration.js +31 -14
  15. package/dist/Keys.js +62 -0
  16. package/dist/ManagedStyles.js +83 -0
  17. package/dist/Render.js +3 -1
  18. package/dist/Runtimes.js +107 -0
  19. package/dist/StaticAreaItem.js +15 -10
  20. package/dist/SystemCSSVars.js +4 -25
  21. package/dist/UI5Element.js +71 -60
  22. package/dist/UI5ElementMetadata.js +18 -2
  23. package/dist/asset-registries/Icons.js +26 -9
  24. package/dist/asset-registries/Illustrations.js +30 -0
  25. package/dist/asset-registries/LocaleData.js +18 -4
  26. package/dist/asset-registries/Themes.js +6 -2
  27. package/dist/asset-registries/i18n.js +3 -1
  28. package/dist/assets/bundle.esm.83f057b4.js +43 -0
  29. package/dist/assets-meta/IconCollectionsAlias.js +18 -0
  30. package/dist/config/Icons.js +52 -0
  31. package/dist/config/Theme.js +25 -0
  32. package/dist/css/BusyIndicator.css +80 -0
  33. package/dist/css/FontFace.css +66 -0
  34. package/dist/css/OverrideFontFace.css +32 -0
  35. package/dist/css/SystemCSSVars.css +17 -0
  36. package/dist/delegate/ItemNavigation.js +75 -4
  37. package/dist/delegate/ScrollEnablement.js +7 -1
  38. package/dist/features/F6Navigation.js +110 -0
  39. package/dist/features/OpenUI5Enablement.js +119 -0
  40. package/dist/generated/AssetParameters.js +1 -1
  41. package/dist/generated/VersionInfo.js +10 -0
  42. package/dist/generated/css/BusyIndicator.css.js +5 -0
  43. package/dist/generated/css/FontFace.css.js +5 -0
  44. package/dist/generated/css/OverrideFontFace.css.js +5 -0
  45. package/dist/generated/css/SystemCSSVars.css.js +5 -0
  46. package/dist/i18nBundle.js +34 -3
  47. package/dist/renderer/LitRenderer.js +39 -18
  48. package/dist/renderer/directives/style-map.js +72 -0
  49. package/dist/renderer/executeTemplate.js +19 -2
  50. package/dist/sap/base/Log.js +241 -0
  51. package/dist/sap/base/assert.js +8 -0
  52. package/dist/sap/base/security/URLListValidator.js +148 -0
  53. package/dist/sap/base/security/encodeCSS.js +14 -0
  54. package/dist/sap/base/security/encodeXML.js +23 -0
  55. package/dist/sap/base/security/sanitizeHTML.js +16 -0
  56. package/dist/sap/base/strings/toHex.js +8 -0
  57. package/dist/sap/base/util/now.js +7 -0
  58. package/dist/sap/ui/thirdparty/caja-html-sanitizer.js +3585 -0
  59. package/dist/theming/CustomStyle.js +23 -3
  60. package/dist/theming/applyTheme.js +11 -10
  61. package/dist/theming/getEffectiveLinksHrefs.js +27 -0
  62. package/dist/theming/getEffectiveStyle.js +9 -0
  63. package/dist/theming/getStylesString.js +4 -2
  64. package/dist/theming/getThemeDesignerTheme.js +25 -5
  65. package/dist/theming/preloadLinks.js +23 -0
  66. package/dist/types/DOMReference.js +24 -0
  67. package/dist/types/DataType.js +12 -0
  68. package/dist/types/Float.js +4 -0
  69. package/dist/types/Integer.js +4 -0
  70. package/dist/types/InvisibleMessageMode.js +30 -0
  71. package/dist/updateShadowRoot.js +9 -6
  72. package/dist/util/AriaLabelHelper.js +6 -8
  73. package/dist/util/Caret.js +1 -14
  74. package/dist/util/ColorConversion.js +30 -2
  75. package/dist/util/FocusableElements.js +13 -7
  76. package/dist/util/HTMLSanitizer.js +7 -0
  77. package/dist/util/InvisibleMessage.js +69 -0
  78. package/dist/util/PopupUtils.js +1 -1
  79. package/dist/util/TabbableElements.js +5 -1
  80. package/dist/util/createLinkInHead.js +19 -0
  81. package/dist/util/escapeRegex.js +10 -0
  82. package/dist/util/generateHighlightedMarkup.js +42 -0
  83. package/dist/util/getEffectiveScrollbarStyle.js +5 -0
  84. package/dist/util/getNormalizedTarget.js +16 -0
  85. package/dist/util/isDefaultSlotProvided.js +11 -0
  86. package/dist/util/isNodeHidden.js +1 -1
  87. package/dist/util/isNodeTabbable.js +4 -4
  88. package/hash.txt +1 -1
  89. package/index.js +1 -1
  90. package/lib/generate-asset-parameters/index.js +8 -5
  91. package/lib/generate-styles/index.js +26 -0
  92. package/lib/generate-version-info/index.js +32 -0
  93. package/package-scripts.js +36 -23
  94. package/package.json +18 -9
  95. package/src/Boot.js +34 -18
  96. package/src/CSP.js +59 -0
  97. package/src/CustomElementsRegistry.js +60 -4
  98. package/src/CustomElementsScope.js +20 -98
  99. package/src/CustomElementsScopeUtils.js +108 -0
  100. package/src/Device.js +22 -1
  101. package/src/EventProvider.js +19 -25
  102. package/src/FeaturesRegistry.js +4 -1
  103. package/src/FontFace.js +7 -95
  104. package/src/InitialConfiguration.js +31 -14
  105. package/src/Keys.js +62 -0
  106. package/src/ManagedStyles.js +83 -0
  107. package/src/Render.js +3 -1
  108. package/src/Runtimes.js +107 -0
  109. package/src/StaticAreaItem.js +15 -10
  110. package/src/SystemCSSVars.js +4 -25
  111. package/src/UI5Element.js +71 -60
  112. package/src/UI5ElementMetadata.js +18 -2
  113. package/src/asset-registries/Icons.js +26 -9
  114. package/src/asset-registries/Illustrations.js +30 -0
  115. package/src/asset-registries/LocaleData.js +18 -4
  116. package/src/asset-registries/Themes.js +6 -2
  117. package/src/asset-registries/i18n.js +3 -1
  118. package/src/assets-meta/IconCollectionsAlias.js +18 -0
  119. package/src/config/Icons.js +52 -0
  120. package/src/config/Theme.js +25 -0
  121. package/src/css/BusyIndicator.css +80 -0
  122. package/src/css/FontFace.css +66 -0
  123. package/src/css/OverrideFontFace.css +32 -0
  124. package/src/css/SystemCSSVars.css +17 -0
  125. package/src/delegate/ItemNavigation.js +75 -4
  126. package/src/delegate/ScrollEnablement.js +7 -1
  127. package/src/features/F6Navigation.js +110 -0
  128. package/src/features/OpenUI5Enablement.js +119 -0
  129. package/src/i18nBundle.js +34 -3
  130. package/src/renderer/LitRenderer.js +39 -18
  131. package/src/renderer/directives/style-map.js +72 -0
  132. package/src/renderer/executeTemplate.js +19 -2
  133. package/src/theming/CustomStyle.js +23 -3
  134. package/src/theming/applyTheme.js +11 -10
  135. package/src/theming/getEffectiveLinksHrefs.js +27 -0
  136. package/src/theming/getEffectiveStyle.js +9 -0
  137. package/src/theming/getStylesString.js +4 -2
  138. package/src/theming/getThemeDesignerTheme.js +25 -5
  139. package/src/theming/preloadLinks.js +23 -0
  140. package/src/types/DOMReference.js +24 -0
  141. package/src/types/DataType.js +12 -0
  142. package/src/types/Float.js +4 -0
  143. package/src/types/Integer.js +4 -0
  144. package/src/types/InvisibleMessageMode.js +30 -0
  145. package/src/updateShadowRoot.js +9 -6
  146. package/src/util/AriaLabelHelper.js +6 -8
  147. package/src/util/Caret.js +1 -14
  148. package/src/util/ColorConversion.js +30 -2
  149. package/src/util/FocusableElements.js +13 -7
  150. package/src/util/HTMLSanitizer.js +7 -0
  151. package/src/util/InvisibleMessage.js +69 -0
  152. package/src/util/PopupUtils.js +1 -1
  153. package/src/util/TabbableElements.js +5 -1
  154. package/src/util/createLinkInHead.js +19 -0
  155. package/src/util/escapeRegex.js +10 -0
  156. package/src/util/generateHighlightedMarkup.js +42 -0
  157. package/src/util/getEffectiveScrollbarStyle.js +5 -0
  158. package/src/util/getNormalizedTarget.js +16 -0
  159. package/src/util/isDefaultSlotProvided.js +11 -0
  160. package/src/util/isNodeHidden.js +1 -1
  161. package/src/util/isNodeTabbable.js +4 -4
  162. package/used-modules.txt +10 -0
  163. package/config/.eslintrc.js +0 -3
  164. package/config/rollup.config.js +0 -1
  165. package/dist/config/AssetsPath.js +0 -17
  166. package/dist/isLegacyBrowser.js +0 -3
  167. package/dist/renderer/ifDefined.js +0 -21
  168. package/dist/renderer/scopeHTML.js +0 -32
  169. package/dist/resources/bundle.esm.js +0 -121
  170. package/dist/resources/bundle.esm.js.map +0 -1
  171. package/dist/test-resources/assets/Themes.js +0 -17
  172. package/dist/test-resources/elements/Child.js +0 -35
  173. package/dist/test-resources/elements/Generic.js +0 -84
  174. package/dist/test-resources/elements/GenericExt.js +0 -26
  175. package/dist/test-resources/elements/NoShadowDOM.js +0 -13
  176. package/dist/test-resources/elements/Parent.js +0 -41
  177. package/dist/test-resources/elements/WithStaticArea.js +0 -76
  178. package/dist/test-resources/pages/AllTestElements.html +0 -39
  179. package/dist/test-resources/pages/Configuration.html +0 -18
  180. package/dist/test-resources/pages/ConfigurationScript.html +0 -34
  181. package/dist/test-resources/pages/assets/messagebundle_de.properties +0 -1
  182. package/dist/test-resources/pages/assets/messagebundle_en.properties +0 -1
  183. package/dist/test-resources/pages/assets/messagebundle_es.properties +0 -1
  184. package/dist/test-resources/pages/assets/messagebundle_fr.properties +0 -1
  185. package/dist/test-resources/pages/i18n.html +0 -35
  186. package/dist/test-resources/specs/ConfigurationChange.spec.js +0 -27
  187. package/dist/test-resources/specs/ConfigurationScript.spec.js +0 -63
  188. package/dist/test-resources/specs/ConfigurationURL.spec.js +0 -47
  189. package/dist/test-resources/specs/CustomTheme.spec.js +0 -27
  190. package/dist/test-resources/specs/StaticArea.spec.js +0 -36
  191. package/dist/test-resources/specs/Theming.spec.js +0 -33
  192. package/dist/test-resources/specs/UI5ElementInvalidation.js +0 -242
  193. package/dist/test-resources/specs/UI5ElementLifecycle.js +0 -98
  194. package/dist/test-resources/specs/UI5ElementListenForChildPropChanges.spec.js +0 -75
  195. package/dist/test-resources/specs/UI5ElementMetadataExt.js +0 -42
  196. package/dist/test-resources/specs/UI5ElementPropertyValidation.js +0 -14
  197. package/dist/test-resources/specs/UI5ElementPropsAndAttrs.spec.js +0 -67
  198. package/dist/test-resources/specs/UI5ElementShadowDOM.js +0 -24
  199. package/dist/test-resources/specs/UI5ElementSlots.js +0 -36
  200. package/dist/theming/createThemePropertiesStyleTag.js +0 -20
  201. package/dist/util/encodeCSS.js +0 -24
  202. package/dist/util/findNodeOwner.js +0 -35
  203. package/src/config/AssetsPath.js +0 -17
  204. package/src/isLegacyBrowser.js +0 -3
  205. package/src/renderer/ifDefined.js +0 -21
  206. package/src/renderer/scopeHTML.js +0 -32
  207. package/src/theming/createThemePropertiesStyleTag.js +0 -20
  208. package/src/util/encodeCSS.js +0 -24
  209. package/src/util/findNodeOwner.js +0 -35
@@ -10,15 +10,15 @@ import { registerTag, isTagRegistered, recordTagRegistrationFailure } from "./Cu
10
10
  import { observeDOMNode, unobserveDOMNode } from "./DOMObserver.js";
11
11
  import { skipOriginalEvent } from "./config/NoConflict.js";
12
12
  import getEffectiveDir from "./locale/getEffectiveDir.js";
13
- import Integer from "./types/Integer.js";
14
- import Float from "./types/Float.js";
13
+ import DataType from "./types/DataType.js";
15
14
  import { kebabToCamelCase, camelToKebabCase } from "./util/StringHelper.js";
16
15
  import isValidPropertyName from "./util/isValidPropertyName.js";
16
+ import isDescendantOf from "./util/isDescendantOf.js";
17
17
  import { isSlot, getSlotName, getSlottedElementsList } from "./util/SlotsHelper.js";
18
18
  import arraysAreEqual from "./util/arraysAreEqual.js";
19
19
  import getClassCopy from "./util/getClassCopy.js";
20
20
  import { markAsRtlAware } from "./locale/RTLAwareRegistry.js";
21
- import isLegacyBrowser from "./isLegacyBrowser.js";
21
+ import preloadLinks from "./theming/preloadLinks.js";
22
22
 
23
23
  let autoId = 0;
24
24
 
@@ -43,9 +43,11 @@ function _invalidate(changeInfo) {
43
43
 
44
44
  this._changedState.push(changeInfo);
45
45
  renderDeferred(this);
46
- this._eventProvider.fireEvent("change", { ...changeInfo, target: this });
46
+ this._eventProvider.fireEvent("invalidate", { ...changeInfo, target: this });
47
47
  }
48
48
 
49
+ let metadata = {};
50
+
49
51
  /**
50
52
  * Base class for all UI5 Web Components
51
53
  *
@@ -72,6 +74,7 @@ class UI5Element extends HTMLElement {
72
74
  deferredResolve = resolve;
73
75
  });
74
76
  this._domRefReadyPromise._deferredResolve = deferredResolve;
77
+ this._doNotSyncAttributes = new Set(); // attributes that are excluded from attributeChangedCallback synchronization
75
78
 
76
79
  this._initializeState();
77
80
  this._upgradeAllProperties();
@@ -101,8 +104,10 @@ class UI5Element extends HTMLElement {
101
104
  */
102
105
  async connectedCallback() {
103
106
  this.setAttribute(this.constructor.getMetadata().getPureTag(), "");
107
+ if (this.constructor.getMetadata().supportsF6FastNavigation()) {
108
+ this.setAttribute("data-sap-ui-fastnavgroup", "true");
109
+ }
104
110
 
105
- const needsShadowDOM = this.constructor._needsShadowDOM();
106
111
  const slotsAreManaged = this.constructor.getMetadata().slotsAreManaged();
107
112
 
108
113
  this._inDOM = true;
@@ -113,10 +118,6 @@ class UI5Element extends HTMLElement {
113
118
  await this._processChildren();
114
119
  }
115
120
 
116
- if (needsShadowDOM && !this.shadowRoot) { // Workaround for Firefox74 bug
117
- await Promise.resolve();
118
- }
119
-
120
121
  if (!this._inDOM) { // Component removed from DOM while _processChildren was running
121
122
  return;
122
123
  }
@@ -134,7 +135,6 @@ class UI5Element extends HTMLElement {
134
135
  * @private
135
136
  */
136
137
  disconnectedCallback() {
137
- const needsShadowDOM = this.constructor._needsShadowDOM();
138
138
  const slotsAreManaged = this.constructor.getMetadata().slotsAreManaged();
139
139
 
140
140
  this._inDOM = false;
@@ -143,13 +143,11 @@ class UI5Element extends HTMLElement {
143
143
  this._stopObservingDOMChildren();
144
144
  }
145
145
 
146
- if (needsShadowDOM) {
147
- if (this._fullyConnected) {
148
- if (typeof this.onExitDOM === "function") {
149
- this.onExitDOM();
150
- }
151
- this._fullyConnected = false;
146
+ if (this._fullyConnected) {
147
+ if (typeof this.onExitDOM === "function") {
148
+ this.onExitDOM();
152
149
  }
150
+ this._fullyConnected = false;
153
151
  }
154
152
 
155
153
  if (this.staticAreaItem && this.staticAreaItem.parentElement) {
@@ -259,7 +257,8 @@ class UI5Element extends HTMLElement {
259
257
 
260
258
  // Listen for any invalidation on the child if invalidateOnChildChange is true or an object (ignore when false or not set)
261
259
  if (child.isUI5Element && slotData.invalidateOnChildChange) {
262
- child._attachChange(this._getChildChangeListener(slotName));
260
+ const method = (child.attachInvalidate || child._attachChange).bind(child);
261
+ method(this._getChildChangeListener(slotName));
263
262
  }
264
263
 
265
264
  // Listen for the slotchange event if the child is a slot itself
@@ -319,7 +318,8 @@ class UI5Element extends HTMLElement {
319
318
 
320
319
  children.forEach(child => {
321
320
  if (child && child.isUI5Element) {
322
- child._detachChange(this._getChildChangeListener(slotName));
321
+ const method = (child.detachInvalidate || child._detachChange).bind(child);
322
+ method(this._getChildChangeListener(slotName));
323
323
  }
324
324
 
325
325
  if (isSlot(child)) {
@@ -334,20 +334,20 @@ class UI5Element extends HTMLElement {
334
334
  * Attach a callback that will be executed whenever the component is invalidated
335
335
  *
336
336
  * @param callback
337
- * @protected
337
+ * @public
338
338
  */
339
- _attachChange(callback) {
340
- this._eventProvider.attachEvent("change", callback);
339
+ attachInvalidate(callback) {
340
+ this._eventProvider.attachEvent("invalidate", callback);
341
341
  }
342
342
 
343
343
  /**
344
344
  * Detach the callback that is executed whenever the component is invalidated
345
345
  *
346
346
  * @param callback
347
- * @protected
347
+ * @public
348
348
  */
349
- _detachChange(callback) {
350
- this._eventProvider.detachEvent("change", callback);
349
+ detachInvalidate(callback) {
350
+ this._eventProvider.detachEvent("invalidate", callback);
351
351
  }
352
352
 
353
353
  /**
@@ -377,6 +377,10 @@ class UI5Element extends HTMLElement {
377
377
  * @private
378
378
  */
379
379
  attributeChangedCallback(name, oldValue, newValue) {
380
+ if (this._doNotSyncAttributes.has(name)) { // This attribute is mutated internally, not by the user
381
+ return;
382
+ }
383
+
380
384
  const properties = this.constructor.getMetadata().getProperties();
381
385
  const realName = name.replace(/^ui5-/, "");
382
386
  const nameInCamelCase = kebabToCamelCase(realName);
@@ -384,12 +388,8 @@ class UI5Element extends HTMLElement {
384
388
  const propertyTypeClass = properties[nameInCamelCase].type;
385
389
  if (propertyTypeClass === Boolean) {
386
390
  newValue = newValue !== null;
387
- }
388
- if (propertyTypeClass === Integer) {
389
- newValue = parseInt(newValue);
390
- }
391
- if (propertyTypeClass === Float) {
392
- newValue = parseFloat(newValue);
391
+ } else if (isDescendantOf(propertyTypeClass, DataType)) {
392
+ newValue = propertyTypeClass.attributeToProperty(newValue);
393
393
  }
394
394
  this[nameInCamelCase] = newValue;
395
395
  }
@@ -402,22 +402,31 @@ class UI5Element extends HTMLElement {
402
402
  if (!this.constructor.getMetadata().hasAttribute(name)) {
403
403
  return;
404
404
  }
405
-
406
- if (typeof newValue === "object") {
407
- return;
408
- }
409
-
405
+ const properties = this.constructor.getMetadata().getProperties();
406
+ const propertyTypeClass = properties[name].type;
410
407
  const attrName = camelToKebabCase(name);
411
408
  const attrValue = this.getAttribute(attrName);
412
- if (typeof newValue === "boolean") {
409
+
410
+ if (propertyTypeClass === Boolean) {
413
411
  if (newValue === true && attrValue === null) {
414
412
  this.setAttribute(attrName, "");
415
413
  } else if (newValue === false && attrValue !== null) {
416
414
  this.removeAttribute(attrName);
417
415
  }
418
- } else if (attrValue !== newValue) {
419
- this.setAttribute(attrName, newValue);
420
- }
416
+ } else if (isDescendantOf(propertyTypeClass, DataType)) {
417
+ const newAttrValue = propertyTypeClass.propertyToAttribute(newValue);
418
+ if (newAttrValue === null) { // null means there must be no attribute for the current value of the property
419
+ this._doNotSyncAttributes.add(attrName); // skip the attributeChangedCallback call for this attribute
420
+ this.removeAttribute(attrName); // remove the attribute safely (will not trigger synchronization to the property value due to the above line)
421
+ this._doNotSyncAttributes.delete(attrName); // enable synchronization again for this attribute
422
+ } else {
423
+ this.setAttribute(attrName, newAttrValue);
424
+ }
425
+ } else if (typeof newValue !== "object") {
426
+ if (attrValue !== newValue) {
427
+ this.setAttribute(attrName, newValue);
428
+ }
429
+ } // else { return; } // old object handling
421
430
  }
422
431
 
423
432
  /**
@@ -617,25 +626,27 @@ class UI5Element extends HTMLElement {
617
626
 
618
627
  /**
619
628
  * Returns the DOM Element inside the Shadow Root that corresponds to the opening tag in the UI5 Web Component's template
629
+ * *Note:* For logical (abstract) elements (items, options, etc...), returns the part of the parent's DOM that represents this option
620
630
  * Use this method instead of "this.shadowRoot" to read the Shadow DOM, if ever necessary
631
+ *
621
632
  * @public
622
633
  */
623
634
  getDomRef() {
635
+ // If a component set _getRealDomRef to its children, use the return value of this function
636
+ if (typeof this._getRealDomRef === "function") {
637
+ return this._getRealDomRef();
638
+ }
639
+
624
640
  if (!this.shadowRoot || this.shadowRoot.children.length === 0) {
625
641
  return;
626
642
  }
627
643
 
628
- this._assertShadowRootStructure();
629
-
630
- return this.shadowRoot.children.length === 1
631
- ? this.shadowRoot.children[0] : this.shadowRoot.children[1];
632
- }
633
-
634
- _assertShadowRootStructure() {
635
- const expectedChildrenCount = document.adoptedStyleSheets || isLegacyBrowser() ? 1 : 2;
636
- if (this.shadowRoot.children.length !== expectedChildrenCount) {
644
+ const children = [...this.shadowRoot.children].filter(child => !["link", "style"].includes(child.localName));
645
+ if (children.length !== 1) {
637
646
  console.warn(`The shadow DOM for ${this.constructor.getMetadata().getTag()} does not have a top level element, the getDomRef() method might not work as expected`); // eslint-disable-line
638
647
  }
648
+
649
+ return children[0];
639
650
  }
640
651
 
641
652
  /**
@@ -661,17 +672,6 @@ class UI5Element extends HTMLElement {
661
672
  return this.getFocusDomRef();
662
673
  }
663
674
 
664
- /**
665
- * Use this method in order to get a reference to an element in the shadow root of the web component or the static area item of the component
666
- * @public
667
- * @method
668
- * @param {String} refName Defines the name of the stable DOM ref
669
- */
670
- getStableDomRef(refName) {
671
- const staticAreaResult = this.staticAreaItem && this.staticAreaItem.getStableDomRef(refName);
672
- return staticAreaResult || this.getDomRef().querySelector(`[data-ui5-stable=${refName}]`);
673
- }
674
-
675
675
  /**
676
676
  * Set the focus to the element, returned by "getFocusDomRef()" (marked by "data-sap-focus-ref")
677
677
  * @public
@@ -861,6 +861,8 @@ class UI5Element extends HTMLElement {
861
861
  const oldState = this._state[prop];
862
862
  if (propData.multiple && propData.compareValues) {
863
863
  isDifferent = !arraysAreEqual(oldState, value);
864
+ } else if (isDescendantOf(propData.type, DataType)) {
865
+ isDifferent = !propData.type.valuesAreEqual(oldState, value);
864
866
  } else {
865
867
  isDifferent = oldState !== value;
866
868
  }
@@ -908,7 +910,15 @@ class UI5Element extends HTMLElement {
908
910
  * @protected
909
911
  */
910
912
  static get metadata() {
911
- return {};
913
+ return metadata;
914
+ }
915
+
916
+ /**
917
+ * Sets a new metadata object for this UI5 Web Component Class
918
+ * @protected
919
+ */
920
+ static set metadata(newMetadata) {
921
+ metadata = newMetadata;
912
922
  }
913
923
 
914
924
  /**
@@ -996,6 +1006,7 @@ class UI5Element extends HTMLElement {
996
1006
  this._generateAccessors();
997
1007
  registerTag(tag);
998
1008
  window.customElements.define(tag, this);
1009
+ preloadLinks(this);
999
1010
 
1000
1011
  if (altTag && !customElements.get(altTag)) {
1001
1012
  registerTag(altTag);
@@ -2,7 +2,7 @@ import DataType from "./types/DataType.js";
2
2
  import isDescendantOf from "./util/isDescendantOf.js";
3
3
  import { camelToKebabCase } from "./util/StringHelper.js";
4
4
  import { getSlottedElements } from "./util/SlotsHelper.js";
5
- import { getEffectiveScopingSuffixForTag } from "./CustomElementsScope.js";
5
+ import { getEffectiveScopingSuffixForTag } from "./CustomElementsScopeUtils.js";
6
6
 
7
7
  /**
8
8
  *
@@ -126,7 +126,7 @@ class UI5ElementMetadata {
126
126
  */
127
127
  hasAttribute(propName) {
128
128
  const propData = this.getProperties()[propName];
129
- return propData.type !== Object && !propData.noAttribute;
129
+ return propData.type !== Object && !propData.noAttribute && !propData.multiple;
130
130
  }
131
131
 
132
132
  /**
@@ -188,6 +188,14 @@ class UI5ElementMetadata {
188
188
  return !!this.metadata.managedSlots;
189
189
  }
190
190
 
191
+ /**
192
+ * Determines whether this control supports F6 fast navigation
193
+ * @public
194
+ */
195
+ supportsF6FastNavigation() {
196
+ return !!this.metadata.fastNavigation;
197
+ }
198
+
191
199
  /**
192
200
  * Returns an object with key-value pairs of properties and their metadata definitions
193
201
  * @public
@@ -212,6 +220,14 @@ class UI5ElementMetadata {
212
220
  return !!this.metadata.languageAware;
213
221
  }
214
222
 
223
+ /**
224
+ * Determines whether this UI5 Element has any theme dependant carachteristics.
225
+ * @returns {boolean}
226
+ */
227
+ isThemeAware() {
228
+ return !!this.metadata.themeAware;
229
+ }
230
+
215
231
  /**
216
232
  * Matches a changed entity (property/slot) with the given name against the "invalidateOnChildChange" configuration
217
233
  * and determines whether this should cause and invalidation
@@ -1,11 +1,12 @@
1
1
  import getSharedResource from "../getSharedResource.js";
2
+ import IconCollectionsAlias from "../assets-meta/IconCollectionsAlias.js";
3
+ import { getEffectiveDefaultIconCollection } from "../config/Icons.js";
2
4
 
3
5
  const loaders = new Map();
4
6
  const registry = getSharedResource("SVGIcons.registry", new Map());
5
7
  const iconCollectionPromises = getSharedResource("SVGIcons.promises", new Map());
6
8
 
7
9
  const ICON_NOT_FOUND = "ICON_NOT_FOUND";
8
- const DEFAULT_COLLECTION = "SAP-icons";
9
10
 
10
11
  /**
11
12
  * @deprecated
@@ -20,6 +21,9 @@ const registerIconLoader = async (collectionName, loader) => {
20
21
 
21
22
  const _loadIconCollectionOnce = async collectionName => {
22
23
  if (!iconCollectionPromises.has(collectionName)) {
24
+ if (!loaders.has(collectionName)) {
25
+ throw new Error(`No loader registered for the ${collectionName} icons collection. Probably you forgot to import the "AllIcons.js" module for the respective package.`);
26
+ }
23
27
  const loadIcons = loaders.get(collectionName);
24
28
  iconCollectionPromises.set(collectionName, loadIcons(collectionName));
25
29
  }
@@ -32,7 +36,7 @@ const _fillRegistry = bundleData => {
32
36
  const iconData = bundleData.data[iconName];
33
37
 
34
38
  registerIcon(iconName, {
35
- pathData: iconData.path,
39
+ pathData: iconData.path || iconData.paths,
36
40
  ltr: iconData.ltr,
37
41
  accData: iconData.acc,
38
42
  collection: bundleData.collection,
@@ -44,7 +48,7 @@ const _fillRegistry = bundleData => {
44
48
  // set
45
49
  const registerIcon = (name, { pathData, ltr, accData, collection, packageName } = {}) => { // eslint-disable-line
46
50
  if (!collection) {
47
- collection = DEFAULT_COLLECTION;
51
+ collection = getEffectiveDefaultIconCollection();
48
52
  }
49
53
 
50
54
  const key = `${collection}/${name}`;
@@ -64,12 +68,16 @@ const _parseName = name => {
64
68
 
65
69
  let collection;
66
70
  [name, collection] = name.split("/").reverse();
67
- collection = collection || DEFAULT_COLLECTION;
68
- // hardcoded alias in case icon explorer is used, resolve `SAP-icons-TNT` to `tnt`
69
- // aliases can be made a feature in the future if more collections need it or more aliases are needed.
70
- if (collection === "SAP-icons-TNT") {
71
- collection = "tnt";
72
- }
71
+ collection = collection || getEffectiveDefaultIconCollection();
72
+
73
+ // Normalize collection name.
74
+ // - resolve `SAP-icons-TNT` to `tnt`.
75
+ // - resolve `BusinessSuiteInAppSymbols` to `business-suite`.
76
+ // - resolve `horizon` to `SAP-icons-v5`,
77
+ // Note: aliases can be made as a feature, if more collections need it or more aliases are needed.
78
+ collection = _normalizeCollection(collection);
79
+ name = name.replace("icon-", "");
80
+
73
81
  const registryKey = `${collection}/${name}`;
74
82
  return { name, collection, registryKey };
75
83
  };
@@ -105,9 +113,18 @@ const _getRegisteredNames = async () => {
105
113
  // fetch one icon of each collection to trigger the bundle load
106
114
  await getIconData("edit");
107
115
  await getIconData("tnt/arrow");
116
+ await getIconData("business-suite/3d");
108
117
  return Array.from(registry.keys());
109
118
  };
110
119
 
120
+ const _normalizeCollection = collectionName => {
121
+ if (IconCollectionsAlias[collectionName]) {
122
+ return IconCollectionsAlias[collectionName];
123
+ }
124
+
125
+ return collectionName;
126
+ };
127
+
111
128
  export {
112
129
  registerIconBundle,
113
130
  registerIconLoader,
@@ -0,0 +1,30 @@
1
+ import getSharedResource from "../getSharedResource.js";
2
+
3
+ const registry = getSharedResource("SVGIllustration.registry", new Map());
4
+ const ILLUSTRATION_NOT_FOUND = "ILLUSTRATION_NOT_FOUND";
5
+
6
+ const registerIllustration = (name, { dialogSvg, sceneSvg, spotSvg, set, title, subtitle } = {}) => { // eslint-disable-line
7
+ registry.set(`${set}/${name}`, {
8
+ dialogSvg,
9
+ sceneSvg,
10
+ spotSvg,
11
+ title,
12
+ subtitle,
13
+ });
14
+ };
15
+
16
+ const getIllustrationDataSync = nameProp => {
17
+ let set = "fiori";
18
+
19
+ if (nameProp.startsWith("Tnt")) {
20
+ set = "tnt";
21
+ nameProp = nameProp.replace(/^Tnt/, "");
22
+ }
23
+
24
+ return registry.get(`${set}/${nameProp}`) || ILLUSTRATION_NOT_FOUND;
25
+ };
26
+
27
+ export {
28
+ getIllustrationDataSync,
29
+ registerIllustration,
30
+ };
@@ -13,14 +13,22 @@ const M_ISO639_OLD_TO_NEW = {
13
13
  "iw": "he",
14
14
  "ji": "yi",
15
15
  "in": "id",
16
- "sh": "sr",
17
16
  };
18
17
 
18
+ const DEV_MODE = false;
19
+
19
20
  const _showAssetsWarningOnce = localeId => {
20
- if (!warningShown) {
21
+ if (warningShown) {
22
+ return;
23
+ }
24
+
25
+ if (!DEV_MODE) {
21
26
  console.warn(`[LocaleData] Supported locale "${localeId}" not configured, import the "Assets.js" module from the webcomponents package you are using.`); /* eslint-disable-line */
22
- warningShown = true;
27
+ } else {
28
+ console.warn(`[LocaleData] Note: in dev mode, CLDR assets might be disabled for performance reasons. Try running "ENABLE_CLDR=1 yarn start" to test CLDR assets.`); /* eslint-disable-line */
23
29
  }
30
+
31
+ warningShown = true;
24
32
  };
25
33
 
26
34
  const calcLocale = (language, region, script) => {
@@ -39,6 +47,12 @@ const calcLocale = (language, region, script) => {
39
47
  }
40
48
  }
41
49
 
50
+ // Special case 3: for Serbian, there are cyrillic and latin scripts, "sh" and "sr-latn" map to "latin", "sr" maps to cyrillic.
51
+ if (language === "sh" || (language === "sr" && script === "Latn")) {
52
+ language = "sr";
53
+ region = "Latn";
54
+ }
55
+
42
56
  // try language + region
43
57
  let localeId = `${language}_${region}`;
44
58
  if (SUPPORTED_LOCALES.includes(localeId)) {
@@ -133,7 +147,7 @@ const registerLocaleDataLoader = (localeId, loader) => {
133
147
 
134
148
  // register default loader for "en" from ui5 CDN (dev workflow without assets)
135
149
  registerLocaleDataLoader("en", async runtimeLocaleId => {
136
- return (await fetch(`https://ui5.sap.com/1.60.2/resources/sap/ui/core/cldr/en.json`)).json();
150
+ return (await fetch(`https://sdk.openui5.org/1.103.0/resources/sap/ui/core/cldr/en.json`)).json();
137
151
  });
138
152
 
139
153
  // When the language changes dynamically (the user calls setLanguage),
@@ -38,10 +38,14 @@ const getThemeProperties = async (packageName, themeName) => {
38
38
 
39
39
  if (!registeredThemes.has(themeName)) {
40
40
  const regThemesStr = [...registeredThemes.values()].join(", ");
41
- console.warn(`You have requested a non-registered theme - falling back to ${DEFAULT_THEME}. Registered themes are: ${regThemesStr}`); /* eslint-disable-line */
42
- return themeStyles.get(`${packageName}_${DEFAULT_THEME}`);
41
+ console.warn(`You have requested a non-registered theme ${themeName} - falling back to ${DEFAULT_THEME}. Registered themes are: ${regThemesStr}`); /* eslint-disable-line */
42
+ return _getThemeProperties(packageName, DEFAULT_THEME);
43
43
  }
44
44
 
45
+ return _getThemeProperties(packageName, themeName);
46
+ };
47
+
48
+ const _getThemeProperties = async (packageName, themeName) => {
45
49
  const loader = loaders.get(`${packageName}/${themeName}`);
46
50
  if (!loader) {
47
51
  // no themes for package
@@ -14,10 +14,12 @@ const bundlePromises = new Map();
14
14
  const loaders = new Map();
15
15
 
16
16
  /**
17
+ * Registers i18n loader function for given package and locale.
17
18
  *
19
+ * @public
18
20
  * @param {string} packageName for which package this loader can fetch data
21
+ * @param {string} localeId locale that this loader can handle
19
22
  * @param {function} loader async function that will be passed a localeId and should return a JSON object
20
- * @param {Array} localeIds Array of locale IDs that this loader can handle
21
23
  */
22
24
  const registerI18nLoader = (packageName, localeId, loader) => {
23
25
  // register loader by key