@ui5/webcomponents-base 0.0.0-6ef02a35f → 0.0.0-7e7d9ea6f

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 (183) hide show
  1. package/.eslintignore +3 -2
  2. package/CHANGELOG.md +225 -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 +20 -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 +11 -7
  15. package/dist/Keys.js +56 -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 +59 -60
  22. package/dist/UI5ElementMetadata.js +47 -6
  23. package/dist/asset-registries/Icons.js +22 -8
  24. package/dist/asset-registries/Illustrations.js +10 -3
  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.691f93f5.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 +75 -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/features/F6Navigation.js +110 -0
  38. package/dist/features/OpenUI5Enablement.js +119 -0
  39. package/dist/generated/AssetParameters.js +1 -1
  40. package/dist/generated/VersionInfo.js +10 -0
  41. package/dist/generated/css/BusyIndicator.css.js +5 -0
  42. package/dist/generated/css/FontFace.css.js +5 -0
  43. package/dist/generated/css/OverrideFontFace.css.js +5 -0
  44. package/dist/generated/css/SystemCSSVars.css.js +5 -0
  45. package/dist/i18nBundle.js +33 -2
  46. package/dist/renderer/LitRenderer.js +33 -12
  47. package/dist/renderer/directives/style-map.js +72 -0
  48. package/dist/renderer/executeTemplate.js +19 -2
  49. package/dist/sap/base/Log.js +2 -10
  50. package/dist/sap/base/assert.js +1 -5
  51. package/dist/sap/base/security/encodeCSS.js +14 -0
  52. package/dist/sap/base/security/encodeXML.js +23 -0
  53. package/dist/sap/base/strings/toHex.js +8 -0
  54. package/dist/sap/ui/thirdparty/caja-html-sanitizer.js +1 -1
  55. package/dist/theming/CustomStyle.js +23 -3
  56. package/dist/theming/applyTheme.js +11 -10
  57. package/dist/theming/getEffectiveLinksHrefs.js +27 -0
  58. package/dist/theming/getEffectiveStyle.js +9 -0
  59. package/dist/theming/getStylesString.js +4 -2
  60. package/dist/theming/getThemeDesignerTheme.js +25 -5
  61. package/dist/theming/preloadLinks.js +23 -0
  62. package/dist/types/DataType.js +12 -0
  63. package/dist/types/Float.js +4 -0
  64. package/dist/types/Integer.js +4 -0
  65. package/dist/updateShadowRoot.js +9 -6
  66. package/dist/util/Caret.js +1 -14
  67. package/dist/util/ColorConversion.js +30 -2
  68. package/dist/util/FocusableElements.js +8 -6
  69. package/dist/util/InvisibleMessage.js +20 -9
  70. package/dist/util/TabbableElements.js +4 -0
  71. package/dist/util/createLinkInHead.js +19 -0
  72. package/dist/util/escapeRegex.js +10 -0
  73. package/dist/util/generateHighlightedMarkup.js +42 -0
  74. package/dist/util/getNormalizedTarget.js +16 -0
  75. package/dist/util/isDefaultSlotProvided.js +11 -0
  76. package/dist/util/isNodeHidden.js +1 -1
  77. package/hash.txt +1 -1
  78. package/lib/generate-asset-parameters/index.js +8 -5
  79. package/lib/generate-styles/index.js +26 -0
  80. package/lib/generate-version-info/index.js +32 -0
  81. package/package-scripts.js +25 -31
  82. package/package.json +11 -12
  83. package/src/Boot.js +34 -18
  84. package/src/CSP.js +59 -0
  85. package/src/CustomElementsRegistry.js +60 -4
  86. package/src/CustomElementsScope.js +20 -98
  87. package/src/CustomElementsScopeUtils.js +108 -0
  88. package/src/Device.js +20 -1
  89. package/src/EventProvider.js +19 -25
  90. package/src/FeaturesRegistry.js +4 -1
  91. package/src/FontFace.js +7 -95
  92. package/src/InitialConfiguration.js +11 -7
  93. package/src/Keys.js +56 -0
  94. package/src/ManagedStyles.js +83 -0
  95. package/src/Render.js +3 -1
  96. package/src/Runtimes.js +107 -0
  97. package/src/StaticAreaItem.js +15 -10
  98. package/src/SystemCSSVars.js +4 -25
  99. package/src/UI5Element.js +59 -60
  100. package/src/UI5ElementMetadata.js +47 -6
  101. package/src/asset-registries/Icons.js +22 -8
  102. package/src/asset-registries/Illustrations.js +10 -3
  103. package/src/asset-registries/LocaleData.js +18 -4
  104. package/src/asset-registries/Themes.js +6 -2
  105. package/src/asset-registries/i18n.js +3 -1
  106. package/src/assets-meta/IconCollectionsAlias.js +18 -0
  107. package/src/config/Icons.js +52 -0
  108. package/src/config/Theme.js +25 -0
  109. package/src/css/BusyIndicator.css +80 -0
  110. package/src/css/FontFace.css +75 -0
  111. package/src/css/OverrideFontFace.css +32 -0
  112. package/src/css/SystemCSSVars.css +17 -0
  113. package/src/delegate/ItemNavigation.js +75 -4
  114. package/src/features/F6Navigation.js +110 -0
  115. package/src/features/OpenUI5Enablement.js +119 -0
  116. package/src/i18nBundle.js +33 -2
  117. package/src/renderer/LitRenderer.js +33 -12
  118. package/src/renderer/directives/style-map.js +72 -0
  119. package/src/renderer/executeTemplate.js +19 -2
  120. package/src/theming/CustomStyle.js +23 -3
  121. package/src/theming/applyTheme.js +11 -10
  122. package/src/theming/getEffectiveLinksHrefs.js +27 -0
  123. package/src/theming/getEffectiveStyle.js +9 -0
  124. package/src/theming/getStylesString.js +4 -2
  125. package/src/theming/getThemeDesignerTheme.js +25 -5
  126. package/src/theming/preloadLinks.js +23 -0
  127. package/src/types/DataType.js +12 -0
  128. package/src/types/Float.js +4 -0
  129. package/src/types/Integer.js +4 -0
  130. package/src/updateShadowRoot.js +9 -6
  131. package/src/util/Caret.js +1 -14
  132. package/src/util/ColorConversion.js +30 -2
  133. package/src/util/FocusableElements.js +8 -6
  134. package/src/util/InvisibleMessage.js +20 -9
  135. package/src/util/TabbableElements.js +4 -0
  136. package/src/util/createLinkInHead.js +19 -0
  137. package/src/util/escapeRegex.js +10 -0
  138. package/src/util/generateHighlightedMarkup.js +42 -0
  139. package/src/util/getNormalizedTarget.js +16 -0
  140. package/src/util/isDefaultSlotProvided.js +11 -0
  141. package/src/util/isNodeHidden.js +1 -1
  142. package/used-modules.txt +4 -1
  143. package/config/.eslintrc.js +0 -3
  144. package/config/rollup.config.js +0 -1
  145. package/dist/config/AssetsPath.js +0 -17
  146. package/dist/isLegacyBrowser.js +0 -3
  147. package/dist/resources/bundle.esm.js +0 -26
  148. package/dist/resources/bundle.esm.js.map +0 -1
  149. package/dist/test-resources/assets/Themes.js +0 -17
  150. package/dist/test-resources/elements/Child.js +0 -35
  151. package/dist/test-resources/elements/Generic.js +0 -84
  152. package/dist/test-resources/elements/GenericExt.js +0 -26
  153. package/dist/test-resources/elements/NoShadowDOM.js +0 -13
  154. package/dist/test-resources/elements/Parent.js +0 -41
  155. package/dist/test-resources/elements/WithStaticArea.js +0 -76
  156. package/dist/test-resources/pages/AllTestElements.html +0 -39
  157. package/dist/test-resources/pages/Configuration.html +0 -18
  158. package/dist/test-resources/pages/ConfigurationScript.html +0 -34
  159. package/dist/test-resources/pages/assets/messagebundle_de.properties +0 -1
  160. package/dist/test-resources/pages/assets/messagebundle_en.properties +0 -1
  161. package/dist/test-resources/pages/assets/messagebundle_es.properties +0 -1
  162. package/dist/test-resources/pages/assets/messagebundle_fr.properties +0 -1
  163. package/dist/test-resources/pages/i18n.html +0 -35
  164. package/dist/test-resources/specs/ConfigurationChange.spec.js +0 -27
  165. package/dist/test-resources/specs/ConfigurationScript.spec.js +0 -63
  166. package/dist/test-resources/specs/ConfigurationURL.spec.js +0 -93
  167. package/dist/test-resources/specs/CustomTheme.spec.js +0 -27
  168. package/dist/test-resources/specs/StaticArea.spec.js +0 -36
  169. package/dist/test-resources/specs/Theming.spec.js +0 -33
  170. package/dist/test-resources/specs/UI5ElementInvalidation.js +0 -242
  171. package/dist/test-resources/specs/UI5ElementLifecycle.js +0 -98
  172. package/dist/test-resources/specs/UI5ElementListenForChildPropChanges.spec.js +0 -75
  173. package/dist/test-resources/specs/UI5ElementMetadataExt.js +0 -42
  174. package/dist/test-resources/specs/UI5ElementPropertyValidation.js +0 -14
  175. package/dist/test-resources/specs/UI5ElementPropsAndAttrs.spec.js +0 -67
  176. package/dist/test-resources/specs/UI5ElementShadowDOM.js +0 -24
  177. package/dist/test-resources/specs/UI5ElementSlots.js +0 -36
  178. package/dist/theming/createThemePropertiesStyleTag.js +0 -20
  179. package/dist/util/encodeCSS.js +0 -24
  180. package/src/config/AssetsPath.js +0 -17
  181. package/src/isLegacyBrowser.js +0 -3
  182. package/src/theming/createThemePropertiesStyleTag.js +0 -20
  183. package/src/util/encodeCSS.js +0 -24
@@ -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
  *
@@ -101,8 +103,10 @@ class UI5Element extends HTMLElement {
101
103
  */
102
104
  async connectedCallback() {
103
105
  this.setAttribute(this.constructor.getMetadata().getPureTag(), "");
106
+ if (this.constructor.getMetadata().supportsF6FastNavigation()) {
107
+ this.setAttribute("data-sap-ui-fastnavgroup", "true");
108
+ }
104
109
 
105
- const needsShadowDOM = this.constructor._needsShadowDOM();
106
110
  const slotsAreManaged = this.constructor.getMetadata().slotsAreManaged();
107
111
 
108
112
  this._inDOM = true;
@@ -113,10 +117,6 @@ class UI5Element extends HTMLElement {
113
117
  await this._processChildren();
114
118
  }
115
119
 
116
- if (needsShadowDOM && !this.shadowRoot) { // Workaround for Firefox74 bug
117
- await Promise.resolve();
118
- }
119
-
120
120
  if (!this._inDOM) { // Component removed from DOM while _processChildren was running
121
121
  return;
122
122
  }
@@ -134,7 +134,6 @@ class UI5Element extends HTMLElement {
134
134
  * @private
135
135
  */
136
136
  disconnectedCallback() {
137
- const needsShadowDOM = this.constructor._needsShadowDOM();
138
137
  const slotsAreManaged = this.constructor.getMetadata().slotsAreManaged();
139
138
 
140
139
  this._inDOM = false;
@@ -143,13 +142,11 @@ class UI5Element extends HTMLElement {
143
142
  this._stopObservingDOMChildren();
144
143
  }
145
144
 
146
- if (needsShadowDOM) {
147
- if (this._fullyConnected) {
148
- if (typeof this.onExitDOM === "function") {
149
- this.onExitDOM();
150
- }
151
- this._fullyConnected = false;
145
+ if (this._fullyConnected) {
146
+ if (typeof this.onExitDOM === "function") {
147
+ this.onExitDOM();
152
148
  }
149
+ this._fullyConnected = false;
153
150
  }
154
151
 
155
152
  if (this.staticAreaItem && this.staticAreaItem.parentElement) {
@@ -259,7 +256,8 @@ class UI5Element extends HTMLElement {
259
256
 
260
257
  // Listen for any invalidation on the child if invalidateOnChildChange is true or an object (ignore when false or not set)
261
258
  if (child.isUI5Element && slotData.invalidateOnChildChange) {
262
- child._attachChange(this._getChildChangeListener(slotName));
259
+ const method = (child.attachInvalidate || child._attachChange).bind(child);
260
+ method(this._getChildChangeListener(slotName));
263
261
  }
264
262
 
265
263
  // Listen for the slotchange event if the child is a slot itself
@@ -319,7 +317,8 @@ class UI5Element extends HTMLElement {
319
317
 
320
318
  children.forEach(child => {
321
319
  if (child && child.isUI5Element) {
322
- child._detachChange(this._getChildChangeListener(slotName));
320
+ const method = (child.detachInvalidate || child._detachChange).bind(child);
321
+ method(this._getChildChangeListener(slotName));
323
322
  }
324
323
 
325
324
  if (isSlot(child)) {
@@ -334,20 +333,20 @@ class UI5Element extends HTMLElement {
334
333
  * Attach a callback that will be executed whenever the component is invalidated
335
334
  *
336
335
  * @param callback
337
- * @protected
336
+ * @public
338
337
  */
339
- _attachChange(callback) {
340
- this._eventProvider.attachEvent("change", callback);
338
+ attachInvalidate(callback) {
339
+ this._eventProvider.attachEvent("invalidate", callback);
341
340
  }
342
341
 
343
342
  /**
344
343
  * Detach the callback that is executed whenever the component is invalidated
345
344
  *
346
345
  * @param callback
347
- * @protected
346
+ * @public
348
347
  */
349
- _detachChange(callback) {
350
- this._eventProvider.detachEvent("change", callback);
348
+ detachInvalidate(callback) {
349
+ this._eventProvider.detachEvent("invalidate", callback);
351
350
  }
352
351
 
353
352
  /**
@@ -384,12 +383,8 @@ class UI5Element extends HTMLElement {
384
383
  const propertyTypeClass = properties[nameInCamelCase].type;
385
384
  if (propertyTypeClass === Boolean) {
386
385
  newValue = newValue !== null;
387
- }
388
- if (propertyTypeClass === Integer) {
389
- newValue = parseInt(newValue);
390
- }
391
- if (propertyTypeClass === Float) {
392
- newValue = parseFloat(newValue);
386
+ } else if (isDescendantOf(propertyTypeClass, DataType)) {
387
+ newValue = propertyTypeClass.attributeToProperty(newValue);
393
388
  }
394
389
  this[nameInCamelCase] = newValue;
395
390
  }
@@ -402,22 +397,24 @@ class UI5Element extends HTMLElement {
402
397
  if (!this.constructor.getMetadata().hasAttribute(name)) {
403
398
  return;
404
399
  }
405
-
406
- if (typeof newValue === "object") {
407
- return;
408
- }
409
-
400
+ const properties = this.constructor.getMetadata().getProperties();
401
+ const propertyTypeClass = properties[name].type;
410
402
  const attrName = camelToKebabCase(name);
411
403
  const attrValue = this.getAttribute(attrName);
412
- if (typeof newValue === "boolean") {
404
+
405
+ if (propertyTypeClass === Boolean) {
413
406
  if (newValue === true && attrValue === null) {
414
407
  this.setAttribute(attrName, "");
415
408
  } else if (newValue === false && attrValue !== null) {
416
409
  this.removeAttribute(attrName);
417
410
  }
418
- } else if (attrValue !== newValue) {
419
- this.setAttribute(attrName, newValue);
420
- }
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
421
418
  }
422
419
 
423
420
  /**
@@ -617,25 +614,27 @@ class UI5Element extends HTMLElement {
617
614
 
618
615
  /**
619
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
620
618
  * Use this method instead of "this.shadowRoot" to read the Shadow DOM, if ever necessary
619
+ *
621
620
  * @public
622
621
  */
623
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
+
624
628
  if (!this.shadowRoot || this.shadowRoot.children.length === 0) {
625
629
  return;
626
630
  }
627
631
 
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) {
632
+ const children = [...this.shadowRoot.children].filter(child => !["link", "style"].includes(child.localName));
633
+ if (children.length !== 1) {
637
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
638
635
  }
636
+
637
+ return children[0];
639
638
  }
640
639
 
641
640
  /**
@@ -661,17 +660,6 @@ class UI5Element extends HTMLElement {
661
660
  return this.getFocusDomRef();
662
661
  }
663
662
 
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
663
  /**
676
664
  * Set the focus to the element, returned by "getFocusDomRef()" (marked by "data-sap-focus-ref")
677
665
  * @public
@@ -861,6 +849,8 @@ class UI5Element extends HTMLElement {
861
849
  const oldState = this._state[prop];
862
850
  if (propData.multiple && propData.compareValues) {
863
851
  isDifferent = !arraysAreEqual(oldState, value);
852
+ } else if (isDescendantOf(propData.type, DataType)) {
853
+ isDifferent = !propData.type.valuesAreEqual(oldState, value);
864
854
  } else {
865
855
  isDifferent = oldState !== value;
866
856
  }
@@ -908,7 +898,15 @@ class UI5Element extends HTMLElement {
908
898
  * @protected
909
899
  */
910
900
  static get metadata() {
911
- return {};
901
+ return metadata;
902
+ }
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;
912
910
  }
913
911
 
914
912
  /**
@@ -996,6 +994,7 @@ class UI5Element extends HTMLElement {
996
994
  this._generateAccessors();
997
995
  registerTag(tag);
998
996
  window.customElements.define(tag, this);
997
+ preloadLinks(this);
999
998
 
1000
999
  if (altTag && !customElements.get(altTag)) {
1001
1000
  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
@@ -281,20 +297,45 @@ class UI5ElementMetadata {
281
297
  }
282
298
  }
283
299
 
300
+ const validateAltTypes = (value, propData, fallbackValue) => {
301
+ let finalValue = fallbackValue;
302
+ const altTypes = propData.altTypes || [];
303
+
304
+ for (let index = 0; index < altTypes.length; index++) {
305
+ const type = altTypes[index];
306
+
307
+ if (type === Boolean && typeof value === "boolean") {
308
+ finalValue = value;
309
+ break;
310
+ } else if (type === String && (typeof value === "string" || typeof value === "undefined" || value === null)) {
311
+ finalValue = value;
312
+ break;
313
+ } else if (type === Object && typeof value === "object") {
314
+ finalValue = value;
315
+ break;
316
+ } else if (isDescendantOf(type, DataType) && type.isValid(value)) {
317
+ finalValue = value;
318
+ break;
319
+ }
320
+ }
321
+
322
+ return finalValue;
323
+ };
324
+
284
325
  const validateSingleProperty = (value, propData) => {
285
326
  const propertyType = propData.type;
286
327
 
287
328
  if (propertyType === Boolean) {
288
- return typeof value === "boolean" ? value : false;
329
+ return typeof value === "boolean" ? value : validateAltTypes(value, propData, false);
289
330
  }
290
331
  if (propertyType === String) {
291
- return (typeof value === "string" || typeof value === "undefined" || value === null) ? value : value.toString();
332
+ return (typeof value === "string" || typeof value === "undefined" || value === null) ? value : validateAltTypes(value, propData, value.toString());
292
333
  }
293
334
  if (propertyType === Object) {
294
- return typeof value === "object" ? value : propData.defaultValue;
335
+ return typeof value === "object" ? value : validateAltTypes(value, propData, propData.defaultValue);
295
336
  }
296
337
  if (isDescendantOf(propertyType, DataType)) {
297
- return propertyType.isValid(value) ? value : propData.defaultValue;
338
+ return propertyType.isValid(value) ? value : validateAltTypes(value, propData, propData.defaultValue);
298
339
  }
299
340
  };
300
341
 
@@ -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
@@ -47,7 +48,7 @@ const _fillRegistry = bundleData => {
47
48
  // set
48
49
  const registerIcon = (name, { pathData, ltr, accData, collection, packageName } = {}) => { // eslint-disable-line
49
50
  if (!collection) {
50
- collection = DEFAULT_COLLECTION;
51
+ collection = getEffectiveDefaultIconCollection();
51
52
  }
52
53
 
53
54
  const key = `${collection}/${name}`;
@@ -67,12 +68,16 @@ const _parseName = name => {
67
68
 
68
69
  let collection;
69
70
  [name, collection] = name.split("/").reverse();
70
- collection = collection || DEFAULT_COLLECTION;
71
- // hardcoded alias in case icon explorer is used, resolve `SAP-icons-TNT` to `tnt`
72
- // aliases can be made a feature in the future if more collections need it or more aliases are needed.
73
- if (collection === "SAP-icons-TNT") {
74
- collection = "tnt";
75
- }
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
+
76
81
  const registryKey = `${collection}/${name}`;
77
82
  return { name, collection, registryKey };
78
83
  };
@@ -108,9 +113,18 @@ const _getRegisteredNames = async () => {
108
113
  // fetch one icon of each collection to trigger the bundle load
109
114
  await getIconData("edit");
110
115
  await getIconData("tnt/arrow");
116
+ await getIconData("business-suite/3d");
111
117
  return Array.from(registry.keys());
112
118
  };
113
119
 
120
+ const _normalizeCollection = collectionName => {
121
+ if (IconCollectionsAlias[collectionName]) {
122
+ return IconCollectionsAlias[collectionName];
123
+ }
124
+
125
+ return collectionName;
126
+ };
127
+
114
128
  export {
115
129
  registerIconBundle,
116
130
  registerIconLoader,
@@ -3,8 +3,8 @@ import getSharedResource from "../getSharedResource.js";
3
3
  const registry = getSharedResource("SVGIllustration.registry", new Map());
4
4
  const ILLUSTRATION_NOT_FOUND = "ILLUSTRATION_NOT_FOUND";
5
5
 
6
- const registerIllustration = (name, { dialogSvg, sceneSvg, spotSvg, title, subtitle } = {}) => { // eslint-disable-line
7
- registry.set(name, {
6
+ const registerIllustration = (name, { dialogSvg, sceneSvg, spotSvg, set, title, subtitle } = {}) => { // eslint-disable-line
7
+ registry.set(`${set}/${name}`, {
8
8
  dialogSvg,
9
9
  sceneSvg,
10
10
  spotSvg,
@@ -14,7 +14,14 @@ const registerIllustration = (name, { dialogSvg, sceneSvg, spotSvg, title, subti
14
14
  };
15
15
 
16
16
  const getIllustrationDataSync = nameProp => {
17
- return registry.get(nameProp) || ILLUSTRATION_NOT_FOUND;
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;
18
25
  };
19
26
 
20
27
  export {
@@ -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://ui5.sap.com/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