@ui5/webcomponents-base 0.0.0-e0658a650 → 0.0.0-e55c2cec6

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 (146) hide show
  1. package/.eslintignore +1 -0
  2. package/dist/Device.d.ts +3 -2
  3. package/dist/Device.js +4 -2
  4. package/dist/Device.js.map +1 -1
  5. package/dist/Keys.js.map +1 -1
  6. package/dist/MarkedEvents.d.ts +9 -0
  7. package/dist/MarkedEvents.js +15 -0
  8. package/dist/MarkedEvents.js.map +1 -0
  9. package/dist/MediaRange.d.ts +3 -2
  10. package/dist/MediaRange.js +50 -48
  11. package/dist/MediaRange.js.map +1 -1
  12. package/dist/UI5Element.d.ts +7 -5
  13. package/dist/UI5Element.js +47 -25
  14. package/dist/UI5Element.js.map +1 -1
  15. package/dist/UI5ElementMetadata.d.ts +14 -11
  16. package/dist/UI5ElementMetadata.js +34 -17
  17. package/dist/UI5ElementMetadata.js.map +1 -1
  18. package/dist/api.json +1 -1
  19. package/dist/asset-registries/Icons.d.ts +1 -1
  20. package/dist/asset-registries/Illustrations.d.ts +4 -3
  21. package/dist/asset-registries/Illustrations.js +3 -3
  22. package/dist/asset-registries/Illustrations.js.map +1 -1
  23. package/dist/assets/bundle.esm.ffad994a.js +56 -0
  24. package/dist/decorators/customElement.d.ts +8 -0
  25. package/dist/decorators/customElement.js +16 -0
  26. package/dist/decorators/customElement.js.map +1 -0
  27. package/dist/decorators/event.d.ts +10 -0
  28. package/dist/decorators/event.js +24 -0
  29. package/dist/decorators/event.js.map +1 -0
  30. package/dist/decorators/fastNavigation.d.ts +7 -0
  31. package/dist/decorators/fastNavigation.js +13 -0
  32. package/dist/decorators/fastNavigation.js.map +1 -0
  33. package/dist/decorators/languageAware.d.ts +7 -0
  34. package/dist/decorators/languageAware.js +13 -0
  35. package/dist/decorators/languageAware.js.map +1 -0
  36. package/dist/decorators/property.d.ts +9 -0
  37. package/dist/decorators/property.js +24 -0
  38. package/dist/decorators/property.js.map +1 -0
  39. package/dist/decorators/slot.d.ts +9 -0
  40. package/dist/decorators/slot.js +37 -0
  41. package/dist/decorators/slot.js.map +1 -0
  42. package/dist/decorators/themeAware.d.ts +7 -0
  43. package/dist/decorators/themeAware.js +13 -0
  44. package/dist/decorators/themeAware.js.map +1 -0
  45. package/dist/delegate/ItemNavigation.d.ts +9 -9
  46. package/dist/delegate/ItemNavigation.js +2 -2
  47. package/dist/delegate/ItemNavigation.js.map +1 -1
  48. package/dist/delegate/ScrollEnablement.d.ts +6 -1
  49. package/dist/delegate/ScrollEnablement.js.map +1 -1
  50. package/dist/generated/VersionInfo.js +3 -3
  51. package/dist/locale/normalizeLocale.js +1 -1
  52. package/dist/sap/base/Log.js +28 -29
  53. package/dist/sap/base/assert.js +5 -6
  54. package/dist/sap/base/security/URLListValidator.js +13 -2
  55. package/dist/theming/getEffectiveLinksHrefs.js +2 -1
  56. package/dist/theming/getEffectiveLinksHrefs.js.map +1 -1
  57. package/dist/theming/getStylesString.d.ts +2 -2
  58. package/dist/theming/getStylesString.js +2 -1
  59. package/dist/theming/getStylesString.js.map +1 -1
  60. package/dist/types/AnimationMode.d.ts +1 -1
  61. package/dist/types/AnimationMode.js +1 -1
  62. package/dist/types/CSSColor.d.ts +2 -2
  63. package/dist/types/CSSColor.js +2 -2
  64. package/dist/types/CalendarType.d.ts +1 -1
  65. package/dist/types/CalendarType.js +1 -1
  66. package/dist/types/DOMReference.d.ts +2 -2
  67. package/dist/types/DOMReference.js +2 -2
  68. package/dist/types/DataType.d.ts +1 -1
  69. package/dist/types/DataType.js +1 -1
  70. package/dist/types/Float.d.ts +2 -2
  71. package/dist/types/Float.js +2 -2
  72. package/dist/types/Integer.d.ts +2 -2
  73. package/dist/types/Integer.js +2 -2
  74. package/dist/types/InvisibleMessageMode.d.ts +1 -1
  75. package/dist/types/InvisibleMessageMode.js +1 -1
  76. package/dist/types/ItemNavigationBehavior.d.ts +1 -1
  77. package/dist/types/ItemNavigationBehavior.js +1 -1
  78. package/dist/types/NavigationMode.d.ts +1 -1
  79. package/dist/types/NavigationMode.js +1 -1
  80. package/dist/types/ValueState.d.ts +1 -1
  81. package/dist/types/ValueState.js +1 -1
  82. package/dist/types.d.ts +9 -4
  83. package/dist/util/Caret.js.map +1 -1
  84. package/dist/util/ColorConversion.d.ts +2 -5
  85. package/dist/util/ColorConversion.js +2 -2
  86. package/dist/util/ColorConversion.js.map +1 -1
  87. package/dist/util/FocusableElements.d.ts +3 -2
  88. package/dist/util/FocusableElements.js.map +1 -1
  89. package/dist/util/PopupUtils.js +5 -5
  90. package/dist/util/PopupUtils.js.map +1 -1
  91. package/dist/util/TabbableElements.d.ts +15 -1
  92. package/dist/util/TabbableElements.js +14 -0
  93. package/dist/util/TabbableElements.js.map +1 -1
  94. package/dist/util/getClassCopy.d.ts +5 -3
  95. package/dist/util/isElementTabbable.d.ts +8 -1
  96. package/dist/util/isElementTabbable.js +8 -0
  97. package/dist/util/isElementTabbable.js.map +1 -1
  98. package/dist/util/willShowContent.d.ts +2 -0
  99. package/dist/util/willShowContent.js +7 -0
  100. package/dist/util/willShowContent.js.map +1 -0
  101. package/package-scripts.js +1 -1
  102. package/package.json +5 -6
  103. package/src/Device.ts +14 -11
  104. package/src/Keys.ts +60 -60
  105. package/src/MarkedEvents.ts +20 -0
  106. package/src/MediaRange.ts +52 -51
  107. package/src/UI5Element.ts +57 -27
  108. package/src/UI5ElementMetadata.ts +49 -24
  109. package/src/asset-registries/Icons.ts +1 -0
  110. package/src/asset-registries/Illustrations.ts +7 -5
  111. package/src/decorators/customElement.ts +17 -0
  112. package/src/decorators/event.ts +28 -0
  113. package/src/decorators/fastNavigation.ts +14 -0
  114. package/src/decorators/languageAware.ts +14 -0
  115. package/src/decorators/property.ts +30 -0
  116. package/src/decorators/slot.ts +49 -0
  117. package/src/decorators/themeAware.ts +14 -0
  118. package/src/delegate/ItemNavigation.ts +9 -9
  119. package/src/delegate/ScrollEnablement.ts +9 -3
  120. package/src/locale/normalizeLocale.ts +1 -1
  121. package/src/theming/getEffectiveLinksHrefs.ts +6 -4
  122. package/src/theming/getStylesString.ts +5 -3
  123. package/src/types/AnimationMode.ts +1 -1
  124. package/src/types/CSSColor.ts +2 -2
  125. package/src/types/CalendarType.ts +1 -1
  126. package/src/types/DOMReference.ts +2 -2
  127. package/src/types/DataType.ts +1 -1
  128. package/src/types/Float.ts +2 -2
  129. package/src/types/Integer.ts +2 -2
  130. package/src/types/InvisibleMessageMode.ts +1 -1
  131. package/src/types/ItemNavigationBehavior.ts +1 -1
  132. package/src/types/NavigationMode.ts +1 -1
  133. package/src/types/ValueState.ts +1 -1
  134. package/src/types.ts +13 -5
  135. package/src/util/Caret.ts +1 -1
  136. package/src/util/ColorConversion.ts +17 -12
  137. package/src/util/FocusableElements.ts +5 -3
  138. package/src/util/PopupUtils.ts +4 -4
  139. package/src/util/TabbableElements.ts +17 -3
  140. package/src/util/isElementTabbable.ts +10 -1
  141. package/src/util/willShowContent.ts +7 -0
  142. package/dist/assets/bundle.esm.72c1d211.js +0 -56
  143. package/dist/util/isDefaultSlotProvided.d.ts +0 -2
  144. package/dist/util/isDefaultSlotProvided.js +0 -10
  145. package/dist/util/isDefaultSlotProvided.js.map +0 -1
  146. package/src/util/isDefaultSlotProvided.ts +0 -11
package/src/MediaRange.ts CHANGED
@@ -1,8 +1,36 @@
1
- const querySets = new Map<string, RangeSet>();
1
+ type Range = Map<string, Array<number>>;
2
2
 
3
- type RangeSet = {
4
- borders: Array<number>,
5
- names: Array<string>,
3
+ const mediaRanges = new Map<string, Range>();
4
+
5
+ const DEAFULT_RANGE_SET: Range = new Map<string, Array<number>>();
6
+ DEAFULT_RANGE_SET.set("S", [0, 599]);
7
+ DEAFULT_RANGE_SET.set("M", [600, 1023]);
8
+ DEAFULT_RANGE_SET.set("L", [1024, 1439]);
9
+ DEAFULT_RANGE_SET.set("XL", [1440, Infinity]);
10
+
11
+ /**
12
+ * Enumeration containing the names and settings of predefined screen width media query range sets.
13
+ *
14
+ * @namespace
15
+ * @name MediaRange.RANGESETS
16
+ * @public
17
+ */
18
+ enum RANGESETS {
19
+ /**
20
+ * A 4-step range set (S-M-L-XL).
21
+ *
22
+ * The ranges of this set are:
23
+ * <ul>
24
+ * <li><code>"S"</code>: For screens smaller than 600 pixels.</li>
25
+ * <li><code>"M"</code>: For screens greater than or equal to 600 pixels and smaller than 1024 pixels.</li>
26
+ * <li><code>"L"</code>: For screens greater than or equal to 1024 pixels and smaller than 1440 pixels.</li>
27
+ * <li><code>"XL"</code>: For screens greater than or equal to 1440 pixels.</li>
28
+ * </ul>
29
+ *
30
+ * @name MediaRange.RANGESETS.RANGE_4STEPS
31
+ * @public
32
+ */
33
+ RANGE_4STEPS = "4Step",
6
34
  }
7
35
 
8
36
  /**
@@ -23,15 +51,11 @@ type RangeSet = {
23
51
  *
24
52
  * @param {string} name The name of the range set to be initialized.
25
53
  * The name must be a valid id and consist only of letters and numeric digits.
26
- * @param {int[]} [borders] The range borders
27
- * @param {string[]} [names] The names of the ranges. The names must be a valid id and consist only of letters and digits.
54
+ * @param {Range} [range] The given range set.
28
55
  * @name MediaRange.initRangeSet
29
56
  */
30
- const _initRangeSet = (name: string, borders: Array<number>, names: Array<string>) => {
31
- querySets.set(name, {
32
- borders,
33
- names,
34
- });
57
+ const initRangeSet = (name: string, range: Range) => {
58
+ mediaRanges.set(name, range);
35
59
  };
36
60
 
37
61
  /**
@@ -41,56 +65,33 @@ const _initRangeSet = (name: string, borders: Array<number>, names: Array<string
41
65
  * otherwise it is determined for the current window size.
42
66
  *
43
67
  * @param {string} name The name of the range set. The range set must be initialized beforehand ({@link MediaRange.initRangeSet})
44
- * @param {int} [width] An optional width, based on which the range should be determined;
45
- * If <code>width</code> is not provided, the window size will be used.
68
+ * @param {number} [width] An optional width, based on which the range should be determined;
69
+ * If <code>width</code> is not provided, the window size will be used.
46
70
  * @returns {string} The name of the current active interval of the range set.
47
71
  *
48
72
  * @name MediaRange.getCurrentRange
49
73
  * @function
50
74
  * @public
51
75
  */
52
- const _getCurrentRange = (name: string, width = window.innerWidth) => {
53
- const querySet = querySets.get(name);
54
- let i = 0;
76
+ const getCurrentRange = (name: string, width = window.innerWidth): string => {
77
+ let rangeSet = mediaRanges.get(name);
55
78
 
56
- if (!querySet) {
57
- return null;
79
+ if (!rangeSet) {
80
+ rangeSet = mediaRanges.get(RANGESETS.RANGE_4STEPS)!;
58
81
  }
59
82
 
60
- for (; i < querySet.borders.length; i++) {
61
- if (width < querySet.borders[i]) {
62
- return querySet.names[i];
83
+ let currentRangeName;
84
+ const effectiveWidth = Math.floor(width);
85
+
86
+ rangeSet.forEach((value, key) => {
87
+ if (effectiveWidth >= value[0] && effectiveWidth <= value[1]) {
88
+ currentRangeName = key;
63
89
  }
64
- }
90
+ });
65
91
 
66
- return querySet.names[i];
92
+ return currentRangeName || [...rangeSet.keys()][0];
67
93
  };
68
94
 
69
- /**
70
- * Enumeration containing the names and settings of predefined screen width media query range sets.
71
- *
72
- * @namespace
73
- * @name MediaRange.RANGESETS
74
- * @public
75
- */
76
- enum RANGESETS {
77
- /**
78
- * A 4-step range set (S-M-L-XL).
79
- *
80
- * The ranges of this set are:
81
- * <ul>
82
- * <li><code>"S"</code>: For screens smaller than 600 pixels.</li>
83
- * <li><code>"M"</code>: For screens greater than or equal to 600 pixels and smaller than 1024 pixels.</li>
84
- * <li><code>"L"</code>: For screens greater than or equal to 1024 pixels and smaller than 1440 pixels.</li>
85
- * <li><code>"XL"</code>: For screens greater than or equal to 1440 pixels.</li>
86
- * </ul>
87
- *
88
- * @name MediaRange.RANGESETS.RANGE_4STEPS
89
- * @public
90
- */
91
- RANGE_4STEPS = "4Step",
92
- }
93
-
94
95
  /**
95
96
  * API for screen width changes.
96
97
  *
@@ -100,10 +101,10 @@ enum RANGESETS {
100
101
 
101
102
  const MediaRange = {
102
103
  RANGESETS,
103
- initRangeSet: _initRangeSet,
104
- getCurrentRange: _getCurrentRange,
104
+ initRangeSet,
105
+ getCurrentRange,
105
106
  };
106
107
 
107
- MediaRange.initRangeSet(MediaRange.RANGESETS.RANGE_4STEPS, [600, 1024, 1440], ["S", "M", "L", "XL"]);
108
+ MediaRange.initRangeSet(MediaRange.RANGESETS.RANGE_4STEPS, DEAFULT_RANGE_SET);
108
109
 
109
110
  export default MediaRange;
package/src/UI5Element.ts CHANGED
@@ -24,7 +24,7 @@ import arraysAreEqual from "./util/arraysAreEqual.js";
24
24
  import { markAsRtlAware } from "./locale/RTLAwareRegistry.js";
25
25
  import preloadLinks from "./theming/preloadLinks.js";
26
26
  import { TemplateFunction, TemplateFunctionResult } from "./renderer/executeTemplate.js";
27
- import { PromiseResolve, StyleData } from "./types.js";
27
+ import { PromiseResolve, ComponentStylesData, ClassMap } from "./types.js";
28
28
 
29
29
  let autoId = 0;
30
30
 
@@ -75,7 +75,7 @@ let metadata = {} as Metadata;
75
75
  * @class
76
76
  * @constructor
77
77
  * @author SAP SE
78
- * @alias sap.ui.webcomponents.base.UI5Element
78
+ * @alias sap.ui.webc.base.UI5Element
79
79
  * @extends HTMLElement
80
80
  * @public
81
81
  */
@@ -291,8 +291,11 @@ abstract class UI5Element extends HTMLElement {
291
291
 
292
292
  // Check if the slotName is supported
293
293
  if (slotData === undefined) {
294
- const validValues = Object.keys(slotsMap).join(", ");
295
- console.warn(`Unknown slotName: ${slotName}, ignoring`, child, `Valid values are: ${validValues}`); // eslint-disable-line
294
+ if (slotName !== "default") {
295
+ const validValues = Object.keys(slotsMap).join(", ");
296
+ console.warn(`Unknown slotName: ${slotName}, ignoring`, child, `Valid values are: ${validValues}`); // eslint-disable-line
297
+ }
298
+
296
299
  return;
297
300
  }
298
301
 
@@ -461,11 +464,18 @@ abstract class UI5Element extends HTMLElement {
461
464
  const realName = name.replace(/^ui5-/, "");
462
465
  const nameInCamelCase = kebabToCamelCase(realName);
463
466
  if (properties.hasOwnProperty(nameInCamelCase)) { // eslint-disable-line
464
- const propertyTypeClass = properties[nameInCamelCase].type;
465
- if (propertyTypeClass === Boolean) {
467
+ const propData = properties[nameInCamelCase];
468
+ const propertyType = propData.type;
469
+ let propertyValidator = propData.validator as typeof DataType;
470
+
471
+ if (propertyType && (propertyType as typeof DataType).isDataTypeClass) {
472
+ propertyValidator = propertyType as typeof DataType;
473
+ }
474
+
475
+ if (propertyValidator) {
476
+ newPropertyValue = propertyValidator.attributeToProperty(newValue);
477
+ } else if (propertyType === Boolean) {
466
478
  newPropertyValue = newValue !== null;
467
- } else if ((propertyTypeClass as typeof DataType).isDataTypeClass) {
468
- newPropertyValue = (propertyTypeClass as typeof DataType).attributeToProperty(newValue);
469
479
  } else {
470
480
  newPropertyValue = newValue as string;
471
481
  }
@@ -484,18 +494,18 @@ abstract class UI5Element extends HTMLElement {
484
494
  return;
485
495
  }
486
496
  const properties = ctor.getMetadata().getProperties();
487
- const propertyTypeClass = properties[name].type;
497
+ const propData = properties[name];
498
+ const propertyType = propData.type;
499
+ let propertyValidator = propData.validator as typeof DataType;
488
500
  const attrName = camelToKebabCase(name);
489
501
  const attrValue = this.getAttribute(attrName);
490
502
 
491
- if (propertyTypeClass === Boolean) {
492
- if (newValue === true && attrValue === null) {
493
- this.setAttribute(attrName, "");
494
- } else if (newValue === false && attrValue !== null) {
495
- this.removeAttribute(attrName);
496
- }
497
- } else if ((propertyTypeClass as typeof DataType).isDataTypeClass) {
498
- const newAttrValue = (propertyTypeClass as typeof DataType).propertyToAttribute(newValue);
503
+ if (propertyType && (propertyType as typeof DataType).isDataTypeClass) {
504
+ propertyValidator = propertyType as typeof DataType;
505
+ }
506
+
507
+ if (propertyValidator) {
508
+ const newAttrValue = propertyValidator.propertyToAttribute(newValue);
499
509
  if (newAttrValue === null) { // null means there must be no attribute for the current value of the property
500
510
  this._doNotSyncAttributes.add(attrName); // skip the attributeChangedCallback call for this attribute
501
511
  this.removeAttribute(attrName); // remove the attribute safely (will not trigger synchronization to the property value due to the above line)
@@ -503,6 +513,12 @@ abstract class UI5Element extends HTMLElement {
503
513
  } else {
504
514
  this.setAttribute(attrName, newAttrValue);
505
515
  }
516
+ } else if (propertyType === Boolean) {
517
+ if (newValue === true && attrValue === null) {
518
+ this.setAttribute(attrName, "");
519
+ } else if (newValue === false && attrValue !== null) {
520
+ this.removeAttribute(attrName);
521
+ }
506
522
  } else if (typeof newValue !== "object") {
507
523
  if (attrValue !== newValue) {
508
524
  this.setAttribute(attrName, newValue as string);
@@ -814,8 +830,8 @@ abstract class UI5Element extends HTMLElement {
814
830
  * Useful when there are transitive slots in nested component scenarios and you don't want to get a list of the slots, but rather of their content.
815
831
  * @public
816
832
  */
817
- getSlottedNodes(this: Record<string, Array<SlotValue>>, slotName: string) {
818
- return getSlottedNodesList(this[slotName]);
833
+ getSlottedNodes(slotName: string) {
834
+ return getSlottedNodesList((this as unknown as Record<string, Array<SlotValue>>)[slotName]);
819
835
  }
820
836
 
821
837
  /**
@@ -839,6 +855,10 @@ abstract class UI5Element extends HTMLElement {
839
855
  return true;
840
856
  }
841
857
 
858
+ get classes(): ClassMap {
859
+ return {};
860
+ }
861
+
842
862
  /**
843
863
  * Do not override this method in derivatives of UI5Element, use metadata properties instead
844
864
  * @private
@@ -935,12 +955,18 @@ abstract class UI5Element extends HTMLElement {
935
955
  const metadataCtor = ctor.getMetadata().constructor as typeof UI5ElementMetadata;
936
956
 
937
957
  value = metadataCtor.validatePropertyValue(value, propData);
938
- const propertyTypeClass = propData.type;
958
+ const propertyType = propData.type;
959
+ let propertyValidator = propData.validator as typeof DataType;
939
960
  const oldState = this._state[prop];
940
- if (Array.isArray(oldState) && Array.isArray(value) && propData.multiple && propData.compareValues) { // compareValues is added for IE, test if needed now
961
+
962
+ if (propertyType && (propertyType as typeof DataType).isDataTypeClass) {
963
+ propertyValidator = propertyType as typeof DataType;
964
+ }
965
+
966
+ if (propertyValidator) {
967
+ isDifferent = !propertyValidator.valuesAreEqual(oldState, value);
968
+ } else if (Array.isArray(oldState) && Array.isArray(value) && propData.multiple && propData.compareValues) { // compareValues is added for IE, test if needed now
941
969
  isDifferent = !arraysAreEqual(oldState, value);
942
- } else if ((propertyTypeClass as typeof DataType).isDataTypeClass) {
943
- isDifferent = !(propertyTypeClass as typeof DataType).valuesAreEqual(oldState, value);
944
970
  } else {
945
971
  isDifferent = oldState !== value;
946
972
  }
@@ -1003,7 +1029,7 @@ abstract class UI5Element extends HTMLElement {
1003
1029
  * Returns the CSS for this UI5 Web Component Class
1004
1030
  * @protected
1005
1031
  */
1006
- static get styles(): Array<StyleData> | StyleData {
1032
+ static get styles(): ComponentStylesData {
1007
1033
  return "";
1008
1034
  }
1009
1035
 
@@ -1011,7 +1037,7 @@ abstract class UI5Element extends HTMLElement {
1011
1037
  * Returns the Static Area CSS for this UI5 Web Component Class
1012
1038
  * @protected
1013
1039
  */
1014
- static get staticAreaStyles(): Array<StyleData> | StyleData {
1040
+ static get staticAreaStyles(): ComponentStylesData {
1015
1041
  return "";
1016
1042
  }
1017
1043
 
@@ -1099,17 +1125,21 @@ abstract class UI5Element extends HTMLElement {
1099
1125
  return this._metadata;
1100
1126
  }
1101
1127
 
1102
- const metadataObjects = [this.metadata];
1128
+ const effectiveMetadata = Object.keys(this.metadata).length ? this.metadata : this.decoratorMetadata;
1129
+ const metadataObjects = [effectiveMetadata];
1103
1130
  let klass = this; // eslint-disable-line
1104
1131
  while (klass !== UI5Element) {
1105
1132
  klass = Object.getPrototypeOf(klass);
1106
- metadataObjects.unshift(klass.metadata);
1133
+ const effectiveKlassMetadata = Object.keys(klass.metadata).length ? klass.metadata : klass.decoratorMetadata;
1134
+ metadataObjects.unshift(effectiveKlassMetadata);
1107
1135
  }
1108
1136
  const mergedMetadata = merge({}, ...metadataObjects) as Metadata;
1109
1137
 
1110
1138
  this._metadata = new UI5ElementMetadata(mergedMetadata);
1111
1139
  return this._metadata;
1112
1140
  }
1141
+
1142
+ static decoratorMetadata: Metadata = {};
1113
1143
  }
1114
1144
 
1115
1145
  /**
@@ -10,6 +10,7 @@ type SlotInvalidation = {
10
10
 
11
11
  type Slot = {
12
12
  type: typeof Node | typeof HTMLElement,
13
+ default?: boolean,
13
14
  propertyName?: string,
14
15
  individualSlots?: boolean,
15
16
  invalidateOnChildChange?: boolean | SlotInvalidation,
@@ -18,21 +19,24 @@ type Slot = {
18
19
  type SlotValue = Node;
19
20
 
20
21
  type Property = {
21
- multiple?: boolean,
22
- type: BooleanConstructor | StringConstructor | ObjectConstructor | DataType
22
+ type?: BooleanConstructor | StringConstructor | ObjectConstructor | DataType
23
+ validator?: DataType,
23
24
  defaultValue?: PropertyValue,
24
25
  noAttribute?: boolean,
26
+ multiple?: boolean,
25
27
  compareValues?: boolean,
26
28
  }
27
29
 
28
30
  type PropertyValue = boolean | number | string | object | undefined | null | DataType;
29
31
 
32
+ type EventData = Record<string, object>;
33
+
30
34
  type Metadata = {
31
- tag: string,
35
+ tag?: string,
32
36
  managedSlots?: boolean,
33
37
  properties?: Record<string, Property>,
34
38
  slots?: Record<string, Slot>,
35
- events?: Record<string, object>,
39
+ events?: EventData,
36
40
  fastNavigation?: boolean,
37
41
  themeAware?: boolean,
38
42
  languageAware?: boolean,
@@ -104,8 +108,8 @@ class UI5ElementMetadata {
104
108
  */
105
109
  static validatePropertyValue(value: PropertyValue, propData: Property) {
106
110
  const isMultiple = propData.multiple;
107
- if (isMultiple && Array.isArray(value)) {
108
- return value.map((propValue: PropertyValue) => validateSingleProperty(propValue, propData));
111
+ if (isMultiple && value) {
112
+ return (value as Array<PropertyValue>).map((propValue: PropertyValue) => validateSingleProperty(propValue, propData));
109
113
  }
110
114
  return validateSingleProperty(value, propData);
111
115
  }
@@ -125,7 +129,7 @@ class UI5ElementMetadata {
125
129
  * @public
126
130
  */
127
131
  getPureTag() {
128
- return this.metadata.tag;
132
+ return this.metadata.tag || "";
129
133
  }
130
134
 
131
135
  /**
@@ -134,6 +138,11 @@ class UI5ElementMetadata {
134
138
  */
135
139
  getTag() {
136
140
  const pureTag = this.metadata.tag;
141
+
142
+ if (!pureTag) {
143
+ return "";
144
+ }
145
+
137
146
  const suffix = getEffectiveScopingSuffixForTag(pureTag);
138
147
  if (!suffix) {
139
148
  return pureTag;
@@ -171,14 +180,6 @@ class UI5ElementMetadata {
171
180
  return this.getPropertiesList().filter(this.hasAttribute.bind(this)).map(camelToKebabCase);
172
181
  }
173
182
 
174
- /**
175
- * Returns an object with key-value pairs of slots and their metadata definitions
176
- * @public
177
- */
178
- getSlots() {
179
- return this.metadata.slots || {};
180
- }
181
-
182
183
  /**
183
184
  * Determines whether this UI5 Element has a default slot of type Node, therefore can slot text
184
185
  * @returns {boolean}
@@ -225,7 +226,10 @@ class UI5ElementMetadata {
225
226
  * @public
226
227
  */
227
228
  getProperties() {
228
- return this.metadata.properties || {};
229
+ if (!this.metadata.properties) {
230
+ this.metadata.properties = {};
231
+ }
232
+ return this.metadata.properties;
229
233
  }
230
234
 
231
235
  /**
@@ -233,7 +237,21 @@ class UI5ElementMetadata {
233
237
  * @public
234
238
  */
235
239
  getEvents() {
236
- return this.metadata.events || {};
240
+ if (!this.metadata.events) {
241
+ this.metadata.events = {};
242
+ }
243
+ return this.metadata.events;
244
+ }
245
+
246
+ /**
247
+ * Returns an object with key-value pairs of slots and their metadata definitions
248
+ * @public
249
+ */
250
+ getSlots() {
251
+ if (!this.metadata.slots) {
252
+ this.metadata.slots = {};
253
+ }
254
+ return this.metadata.slots;
237
255
  }
238
256
 
239
257
  /**
@@ -323,23 +341,29 @@ class UI5ElementMetadata {
323
341
 
324
342
  const validateSingleProperty = (value: PropertyValue, propData: Property) => {
325
343
  const propertyType = propData.type;
344
+ let propertyValidator = propData.validator;
326
345
 
327
- if (propertyType === Boolean) {
328
- return typeof value === "boolean" ? value : false;
346
+ if (propertyType && (propertyType as typeof DataType).isDataTypeClass) {
347
+ propertyValidator = propertyType as typeof DataType;
329
348
  }
330
349
 
331
- if (propertyType === String) {
350
+ if (propertyValidator) {
351
+ return (propertyValidator as typeof DataType).isValid(value) ? value : propData.defaultValue;
352
+ }
353
+
354
+ if (!propertyType || propertyType === String) {
332
355
  return (typeof value === "string" || typeof value === "undefined" || value === null) ? value : value.toString();
333
356
  }
334
357
 
335
- if (propertyType === Object) {
336
- return typeof value === "object" ? value : propData.defaultValue;
358
+ if (propertyType === Boolean) {
359
+ return typeof value === "boolean" ? value : false;
337
360
  }
338
361
 
339
- if ((propertyType as typeof DataType).isDataTypeClass) {
340
- return (propertyType as typeof DataType).isValid(value) ? value : propData.defaultValue;
362
+ if (propertyType === Object) {
363
+ return typeof value === "object" ? value : propData.defaultValue;
341
364
  }
342
365
 
366
+ // Check if "value" is part of the enum (propertyType) values and return the defaultValue if not found.
343
367
  return value as string in propertyType ? value : propData.defaultValue;
344
368
  };
345
369
 
@@ -359,6 +383,7 @@ export type {
359
383
  PropertyValue,
360
384
  Slot,
361
385
  SlotValue,
386
+ EventData,
362
387
  State,
363
388
  Metadata,
364
389
  };
@@ -158,4 +158,5 @@ export {
158
158
 
159
159
  export type {
160
160
  IconData,
161
+ CollectionData,
161
162
  };
@@ -1,4 +1,5 @@
1
1
  import getSharedResource from "../getSharedResource.js";
2
+ import { I18nText } from "../i18nBundle.js";
2
3
 
3
4
  type IllustrationLoader = (illustrationName: string) => Promise<IllustrationData>;
4
5
 
@@ -6,8 +7,8 @@ type IllustrationProperties = {
6
7
  dialogSvg: string,
7
8
  sceneSvg: string,
8
9
  spotSvg: string,
9
- title: string,
10
- subtitle: string,
10
+ title: I18nText,
11
+ subtitle: I18nText,
11
12
  };
12
13
 
13
14
  type IllustrationData = IllustrationProperties & {
@@ -17,7 +18,6 @@ type IllustrationData = IllustrationProperties & {
17
18
  const loaders = new Map<string, IllustrationLoader>();
18
19
  const registry = getSharedResource<Map<string, IllustrationProperties>>("SVGIllustration.registry", new Map());
19
20
  const illustrationPromises = getSharedResource<Map<string, Promise<IllustrationData>>>("SVGIllustration.promises", new Map());
20
- const ILLUSTRATION_NOT_FOUND = "ILLUSTRATION_NOT_FOUND";
21
21
 
22
22
  const registerIllustration = (name: string, data: IllustrationData) => {
23
23
  registry.set(`${data.set}/${name}`, {
@@ -36,8 +36,10 @@ const registerIllustrationLoader = (illustrationName: string, loader: Illustrati
36
36
  const _loadIllustrationOnce = async (illustrationName: string) => {
37
37
  if (!illustrationPromises.has(illustrationName)) {
38
38
  if (!loaders.has(illustrationName)) {
39
- throw new Error(`No loader registered for the ${illustrationName} illustration. Probably you forgot to import the "@ui5/webcomponents-fiori/dist/illustrations/AllIllustrations.js" module.`);
39
+ const illustrationPath = illustrationName.startsWith("Tnt") ? `tnt/${illustrationName.replace(/^Tnt/, "")}` : illustrationName;
40
+ throw new Error(`No loader registered for the ${illustrationName} illustration. Probably you forgot to import the "@ui5/webcomponents-fiori/dist/illustrations/${illustrationPath}.js" module. Or you can import the "@ui5/webcomponents-fiori/dist/illustrations/AllIllustrations.js" module that will make all illustrations available, but fetch only the ones used.`);
40
41
  }
42
+
41
43
  const loadIllustrations = loaders.get(illustrationName)!;
42
44
  illustrationPromises.set(illustrationName, loadIllustrations(illustrationName));
43
45
  }
@@ -62,7 +64,7 @@ const getIllustrationData = async (illustrationName: string) => {
62
64
  set = "tnt";
63
65
  illustrationName = illustrationName.replace(/^Tnt/, "");
64
66
  }
65
- return registry.get(`${set}/${illustrationName}`) || ILLUSTRATION_NOT_FOUND;
67
+ return registry.get(`${set}/${illustrationName}`);
66
68
  };
67
69
 
68
70
  export {
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Returns a custom element class decorator.
3
+ *
4
+ * @param { string } tag
5
+ * @returns { ClassDecorator }
6
+ */
7
+ const customElement = (tag: string): ClassDecorator => {
8
+ return (target: any) => {
9
+ if (!Object.prototype.hasOwnProperty.call(target, "decoratorMetadata")) {
10
+ target.decoratorMetadata = {};
11
+ }
12
+
13
+ target.decoratorMetadata.tag = tag;
14
+ };
15
+ };
16
+
17
+ export default customElement;
@@ -0,0 +1,28 @@
1
+ import { EventData } from "../UI5ElementMetadata.js";
2
+
3
+ /**
4
+ * Returns an event class decorator.
5
+ *
6
+ * @param { string } name the event name
7
+ * @param { EventData } data the event data
8
+ * @returns { ClassDecorator }
9
+ */
10
+ const event = (name: string, data: EventData = {}): ClassDecorator => {
11
+ return (target: any) => {
12
+ if (!Object.prototype.hasOwnProperty.call(target, "decoratorMetadata")) {
13
+ target.decoratorMetadata = {};
14
+ }
15
+
16
+ const decoratorMetadata = target.decoratorMetadata;
17
+ if (!decoratorMetadata.events) {
18
+ decoratorMetadata.events = {};
19
+ }
20
+
21
+ const eventsMetadata = decoratorMetadata.events;
22
+ if (!eventsMetadata[name]) {
23
+ eventsMetadata[name] = data;
24
+ }
25
+ };
26
+ };
27
+
28
+ export default event;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Class decorator, that sets the fastNavigation metadata.
3
+ * @param { any } target the decorated class
4
+ * @returns { void }
5
+ */
6
+ const fastNavigation = (target: any): void => {
7
+ if (!Object.prototype.hasOwnProperty.call(target, "decoratorMetadata")) {
8
+ target.decoratorMetadata = {};
9
+ }
10
+
11
+ target.decoratorMetadata.fastNavigation = true;
12
+ };
13
+
14
+ export default fastNavigation;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Class decorator, that sets the languageAware metadata.
3
+ * @param { any } target the decorated class
4
+ * @returns { void }
5
+ */
6
+ const languageAware = (target: any): void => {
7
+ if (!Object.prototype.hasOwnProperty.call(target, "decoratorMetadata")) {
8
+ target.decoratorMetadata = {};
9
+ }
10
+
11
+ target.decoratorMetadata.languageAware = true;
12
+ };
13
+
14
+ export default languageAware;
@@ -0,0 +1,30 @@
1
+ import type UI5Element from "../UI5Element.js";
2
+ import { Property } from "../UI5ElementMetadata.js";
3
+
4
+ /**
5
+ * Returns a property decorator.
6
+ *
7
+ * @param { Property } propData
8
+ * @returns { PropertyDecorator }
9
+ */
10
+ const property = (propData?: Property): PropertyDecorator => {
11
+ return (target: any, propertyKey: string | symbol) => {
12
+ const ctor = target.constructor as typeof UI5Element;
13
+
14
+ if (!Object.prototype.hasOwnProperty.call(ctor, "decoratorMetadata")) {
15
+ ctor.decoratorMetadata = {};
16
+ }
17
+
18
+ const decoratorMetadata = ctor.decoratorMetadata;
19
+ if (!decoratorMetadata.properties) {
20
+ decoratorMetadata.properties = {};
21
+ }
22
+
23
+ const propsMetadata = decoratorMetadata.properties;
24
+ if (!propsMetadata[propertyKey as string]) {
25
+ propsMetadata[propertyKey as string] = propData || { type: String };
26
+ }
27
+ };
28
+ };
29
+
30
+ export default property;