@ui5/webcomponents-base 0.34.0 → 1.0.1

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 (145) hide show
  1. package/.eslintignore +3 -1
  2. package/CHANGELOG.md +52 -0
  3. package/README.md +26 -2
  4. package/bundle.esm.js +6 -2
  5. package/dist/CSP.js +59 -0
  6. package/dist/Device.js +7 -0
  7. package/dist/EventProvider.js +19 -25
  8. package/dist/FontFace.js +7 -95
  9. package/dist/InitialConfiguration.js +31 -14
  10. package/dist/Keys.js +15 -0
  11. package/dist/ManagedStyles.js +83 -0
  12. package/dist/Render.js +3 -1
  13. package/dist/StaticAreaItem.js +11 -9
  14. package/dist/SystemCSSVars.js +4 -25
  15. package/dist/UI5Element.js +46 -60
  16. package/dist/UI5ElementMetadata.js +9 -1
  17. package/dist/asset-registries/Icons.js +29 -8
  18. package/dist/asset-registries/Illustrations.js +30 -0
  19. package/dist/asset-registries/LocaleData.js +11 -2
  20. package/dist/assets-meta/IconCollectionsAlias.js +18 -0
  21. package/dist/config/Theme.js +14 -0
  22. package/dist/css/FontFace.css +45 -0
  23. package/dist/css/OverrideFontFace.css +32 -0
  24. package/dist/css/SystemCSSVars.css +17 -0
  25. package/dist/delegate/ItemNavigation.js +66 -0
  26. package/dist/delegate/ScrollEnablement.js +7 -1
  27. package/dist/generated/AssetParameters.js +1 -1
  28. package/dist/generated/css/FontFace.css.js +5 -0
  29. package/dist/generated/css/OverrideFontFace.css.js +5 -0
  30. package/dist/generated/css/SystemCSSVars.css.js +5 -0
  31. package/dist/i18nBundle.js +33 -2
  32. package/dist/renderer/LitRenderer.js +24 -21
  33. package/dist/renderer/directives/style-map.js +72 -0
  34. package/dist/resources/bundle.esm.js +17 -101
  35. package/dist/resources/bundle.esm.js.map +1 -1
  36. package/dist/sap/base/Log.js +241 -0
  37. package/dist/sap/base/assert.js +8 -0
  38. package/dist/sap/base/security/URLListValidator.js +148 -0
  39. package/dist/sap/base/security/sanitizeHTML.js +16 -0
  40. package/dist/sap/base/util/now.js +7 -0
  41. package/dist/sap/ui/thirdparty/caja-html-sanitizer.js +3585 -0
  42. package/dist/test-resources/elements/WithStaticArea.js +2 -1
  43. package/dist/test-resources/pages/AllTestElements.html +3 -0
  44. package/dist/test-resources/pages/i18n.html +1 -3
  45. package/dist/test-resources/specs/ConfigurationChange.spec.js +9 -9
  46. package/dist/test-resources/specs/ConfigurationScript.spec.js +24 -24
  47. package/dist/test-resources/specs/ConfigurationURL.spec.js +64 -18
  48. package/dist/test-resources/specs/CustomTheme.spec.js +7 -7
  49. package/dist/test-resources/specs/EventProvider.spec.js +63 -0
  50. package/dist/test-resources/specs/StaticArea.spec.js +55 -13
  51. package/dist/test-resources/specs/Theming.spec.js +11 -11
  52. package/dist/test-resources/specs/UI5ElementInvalidation.js +29 -29
  53. package/dist/test-resources/specs/UI5ElementLifecycle.js +11 -11
  54. package/dist/test-resources/specs/UI5ElementListenForChildPropChanges.spec.js +11 -11
  55. package/dist/test-resources/specs/UI5ElementMetadataExt.js +8 -8
  56. package/dist/test-resources/specs/UI5ElementPropertyValidation.js +6 -6
  57. package/dist/test-resources/specs/UI5ElementPropsAndAttrs.spec.js +36 -36
  58. package/dist/test-resources/specs/UI5ElementShadowDOM.js +9 -9
  59. package/dist/test-resources/specs/UI5ElementSlots.js +9 -9
  60. package/dist/theming/CustomStyle.js +23 -3
  61. package/dist/theming/applyTheme.js +5 -8
  62. package/dist/theming/getEffectiveLinksHrefs.js +20 -0
  63. package/dist/theming/getStylesString.js +4 -2
  64. package/dist/theming/getThemeDesignerTheme.js +2 -1
  65. package/dist/theming/preloadLinks.js +23 -0
  66. package/dist/types/DataType.js +12 -0
  67. package/dist/types/Float.js +4 -0
  68. package/dist/types/Integer.js +4 -0
  69. package/dist/types/InvisibleMessageMode.js +30 -0
  70. package/dist/updateShadowRoot.js +8 -4
  71. package/dist/util/AriaLabelHelper.js +4 -4
  72. package/dist/util/FocusableElements.js +5 -1
  73. package/dist/util/HTMLSanitizer.js +7 -0
  74. package/dist/util/InvisibleMessage.js +58 -0
  75. package/dist/util/PopupUtils.js +1 -1
  76. package/dist/util/TabbableElements.js +1 -1
  77. package/dist/util/createLinkInHead.js +19 -0
  78. package/dist/util/encodeXML.js +35 -0
  79. package/dist/util/escapeRegex.js +10 -0
  80. package/dist/util/generateHighlightedMarkup.js +42 -0
  81. package/dist/util/getClassCopy.js +7 -2
  82. package/dist/util/isNodeTabbable.js +4 -4
  83. package/hash.txt +1 -1
  84. package/index.js +1 -1
  85. package/lib/generate-asset-parameters/index.js +0 -1
  86. package/lib/generate-styles/index.js +18 -0
  87. package/package-scripts.js +25 -3
  88. package/package.json +17 -9
  89. package/src/CSP.js +59 -0
  90. package/src/Device.js +7 -0
  91. package/src/EventProvider.js +19 -25
  92. package/src/FontFace.js +7 -95
  93. package/src/InitialConfiguration.js +31 -14
  94. package/src/Keys.js +15 -0
  95. package/src/ManagedStyles.js +83 -0
  96. package/src/Render.js +3 -1
  97. package/src/StaticAreaItem.js +11 -9
  98. package/src/SystemCSSVars.js +4 -25
  99. package/src/UI5Element.js +46 -60
  100. package/src/UI5ElementMetadata.js +9 -1
  101. package/src/asset-registries/Icons.js +29 -8
  102. package/src/asset-registries/Illustrations.js +30 -0
  103. package/src/asset-registries/LocaleData.js +11 -2
  104. package/src/assets-meta/IconCollectionsAlias.js +18 -0
  105. package/src/config/Theme.js +14 -0
  106. package/src/css/FontFace.css +45 -0
  107. package/src/css/OverrideFontFace.css +32 -0
  108. package/src/css/SystemCSSVars.css +17 -0
  109. package/src/delegate/ItemNavigation.js +66 -0
  110. package/src/delegate/ScrollEnablement.js +7 -1
  111. package/src/i18nBundle.js +33 -2
  112. package/src/renderer/LitRenderer.js +24 -21
  113. package/src/renderer/directives/style-map.js +72 -0
  114. package/src/theming/CustomStyle.js +23 -3
  115. package/src/theming/applyTheme.js +5 -8
  116. package/src/theming/getEffectiveLinksHrefs.js +20 -0
  117. package/src/theming/getStylesString.js +4 -2
  118. package/src/theming/getThemeDesignerTheme.js +2 -1
  119. package/src/theming/preloadLinks.js +23 -0
  120. package/src/types/DataType.js +12 -0
  121. package/src/types/Float.js +4 -0
  122. package/src/types/Integer.js +4 -0
  123. package/src/types/InvisibleMessageMode.js +30 -0
  124. package/src/updateShadowRoot.js +8 -4
  125. package/src/util/AriaLabelHelper.js +4 -4
  126. package/src/util/FocusableElements.js +5 -1
  127. package/src/util/HTMLSanitizer.js +7 -0
  128. package/src/util/InvisibleMessage.js +58 -0
  129. package/src/util/PopupUtils.js +1 -1
  130. package/src/util/TabbableElements.js +1 -1
  131. package/src/util/createLinkInHead.js +19 -0
  132. package/src/util/encodeXML.js +35 -0
  133. package/src/util/escapeRegex.js +10 -0
  134. package/src/util/generateHighlightedMarkup.js +42 -0
  135. package/src/util/getClassCopy.js +7 -2
  136. package/src/util/isNodeTabbable.js +4 -4
  137. package/used-modules.txt +7 -0
  138. package/dist/config/AssetsPath.js +0 -17
  139. package/dist/renderer/ifDefined.js +0 -21
  140. package/dist/renderer/scopeHTML.js +0 -32
  141. package/dist/theming/createThemePropertiesStyleTag.js +0 -20
  142. package/src/config/AssetsPath.js +0 -17
  143. package/src/renderer/ifDefined.js +0 -21
  144. package/src/renderer/scopeHTML.js +0 -32
  145. package/src/theming/createThemePropertiesStyleTag.js +0 -20
package/src/UI5Element.js CHANGED
@@ -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,7 +43,7 @@ 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
49
  /**
@@ -102,7 +102,6 @@ class UI5Element extends HTMLElement {
102
102
  async connectedCallback() {
103
103
  this.setAttribute(this.constructor.getMetadata().getPureTag(), "");
104
104
 
105
- const needsShadowDOM = this.constructor._needsShadowDOM();
106
105
  const slotsAreManaged = this.constructor.getMetadata().slotsAreManaged();
107
106
 
108
107
  this._inDOM = true;
@@ -113,10 +112,6 @@ class UI5Element extends HTMLElement {
113
112
  await this._processChildren();
114
113
  }
115
114
 
116
- if (needsShadowDOM && !this.shadowRoot) { // Workaround for Firefox74 bug
117
- await Promise.resolve();
118
- }
119
-
120
115
  if (!this._inDOM) { // Component removed from DOM while _processChildren was running
121
116
  return;
122
117
  }
@@ -134,7 +129,6 @@ class UI5Element extends HTMLElement {
134
129
  * @private
135
130
  */
136
131
  disconnectedCallback() {
137
- const needsShadowDOM = this.constructor._needsShadowDOM();
138
132
  const slotsAreManaged = this.constructor.getMetadata().slotsAreManaged();
139
133
 
140
134
  this._inDOM = false;
@@ -143,13 +137,11 @@ class UI5Element extends HTMLElement {
143
137
  this._stopObservingDOMChildren();
144
138
  }
145
139
 
146
- if (needsShadowDOM) {
147
- if (this._fullyConnected) {
148
- if (typeof this.onExitDOM === "function") {
149
- this.onExitDOM();
150
- }
151
- this._fullyConnected = false;
140
+ if (this._fullyConnected) {
141
+ if (typeof this.onExitDOM === "function") {
142
+ this.onExitDOM();
152
143
  }
144
+ this._fullyConnected = false;
153
145
  }
154
146
 
155
147
  if (this.staticAreaItem && this.staticAreaItem.parentElement) {
@@ -259,7 +251,7 @@ class UI5Element extends HTMLElement {
259
251
 
260
252
  // Listen for any invalidation on the child if invalidateOnChildChange is true or an object (ignore when false or not set)
261
253
  if (child.isUI5Element && slotData.invalidateOnChildChange) {
262
- child._attachChange(this._getChildChangeListener(slotName));
254
+ child.attachInvalidate(this._getChildChangeListener(slotName));
263
255
  }
264
256
 
265
257
  // Listen for the slotchange event if the child is a slot itself
@@ -319,7 +311,7 @@ class UI5Element extends HTMLElement {
319
311
 
320
312
  children.forEach(child => {
321
313
  if (child && child.isUI5Element) {
322
- child._detachChange(this._getChildChangeListener(slotName));
314
+ child.detachInvalidate(this._getChildChangeListener(slotName));
323
315
  }
324
316
 
325
317
  if (isSlot(child)) {
@@ -334,20 +326,20 @@ class UI5Element extends HTMLElement {
334
326
  * Attach a callback that will be executed whenever the component is invalidated
335
327
  *
336
328
  * @param callback
337
- * @protected
329
+ * @public
338
330
  */
339
- _attachChange(callback) {
340
- this._eventProvider.attachEvent("change", callback);
331
+ attachInvalidate(callback) {
332
+ this._eventProvider.attachEvent("invalidate", callback);
341
333
  }
342
334
 
343
335
  /**
344
336
  * Detach the callback that is executed whenever the component is invalidated
345
337
  *
346
338
  * @param callback
347
- * @protected
339
+ * @public
348
340
  */
349
- _detachChange(callback) {
350
- this._eventProvider.detachEvent("change", callback);
341
+ detachInvalidate(callback) {
342
+ this._eventProvider.detachEvent("invalidate", callback);
351
343
  }
352
344
 
353
345
  /**
@@ -384,12 +376,8 @@ class UI5Element extends HTMLElement {
384
376
  const propertyTypeClass = properties[nameInCamelCase].type;
385
377
  if (propertyTypeClass === Boolean) {
386
378
  newValue = newValue !== null;
387
- }
388
- if (propertyTypeClass === Integer) {
389
- newValue = parseInt(newValue);
390
- }
391
- if (propertyTypeClass === Float) {
392
- newValue = parseFloat(newValue);
379
+ } else if (isDescendantOf(propertyTypeClass, DataType)) {
380
+ newValue = propertyTypeClass.attributeToProperty(newValue);
393
381
  }
394
382
  this[nameInCamelCase] = newValue;
395
383
  }
@@ -402,22 +390,24 @@ class UI5Element extends HTMLElement {
402
390
  if (!this.constructor.getMetadata().hasAttribute(name)) {
403
391
  return;
404
392
  }
405
-
406
- if (typeof newValue === "object") {
407
- return;
408
- }
409
-
393
+ const properties = this.constructor.getMetadata().getProperties();
394
+ const propertyTypeClass = properties[name].type;
410
395
  const attrName = camelToKebabCase(name);
411
396
  const attrValue = this.getAttribute(attrName);
412
- if (typeof newValue === "boolean") {
397
+
398
+ if (propertyTypeClass === Boolean) {
413
399
  if (newValue === true && attrValue === null) {
414
400
  this.setAttribute(attrName, "");
415
401
  } else if (newValue === false && attrValue !== null) {
416
402
  this.removeAttribute(attrName);
417
403
  }
418
- } else if (attrValue !== newValue) {
419
- this.setAttribute(attrName, newValue);
420
- }
404
+ } else if (isDescendantOf(propertyTypeClass, DataType)) {
405
+ this.setAttribute(attrName, propertyTypeClass.propertyToAttribute(newValue));
406
+ } else if (typeof newValue !== "object") {
407
+ if (attrValue !== newValue) {
408
+ this.setAttribute(attrName, newValue);
409
+ }
410
+ } // else { return; } // old object handling
421
411
  }
422
412
 
423
413
  /**
@@ -617,25 +607,27 @@ class UI5Element extends HTMLElement {
617
607
 
618
608
  /**
619
609
  * Returns the DOM Element inside the Shadow Root that corresponds to the opening tag in the UI5 Web Component's template
610
+ * *Note:* For logical (abstract) elements (items, options, etc...), returns the part of the parent's DOM that represents this option
620
611
  * Use this method instead of "this.shadowRoot" to read the Shadow DOM, if ever necessary
612
+ *
621
613
  * @public
622
614
  */
623
615
  getDomRef() {
616
+ // If a component set _getRealDomRef to its children, use the return value of this function
617
+ if (typeof this._getRealDomRef === "function") {
618
+ return this._getRealDomRef();
619
+ }
620
+
624
621
  if (!this.shadowRoot || this.shadowRoot.children.length === 0) {
625
622
  return;
626
623
  }
627
624
 
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) {
625
+ const children = [...this.shadowRoot.children].filter(child => !["link", "style"].includes(child.localName));
626
+ if (children.length !== 1) {
637
627
  console.warn(`The shadow DOM for ${this.constructor.getMetadata().getTag()} does not have a top level element, the getDomRef() method might not work as expected`); // eslint-disable-line
638
628
  }
629
+
630
+ return children[0];
639
631
  }
640
632
 
641
633
  /**
@@ -661,17 +653,6 @@ class UI5Element extends HTMLElement {
661
653
  return this.getFocusDomRef();
662
654
  }
663
655
 
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
656
  /**
676
657
  * Set the focus to the element, returned by "getFocusDomRef()" (marked by "data-sap-focus-ref")
677
658
  * @public
@@ -861,6 +842,8 @@ class UI5Element extends HTMLElement {
861
842
  const oldState = this._state[prop];
862
843
  if (propData.multiple && propData.compareValues) {
863
844
  isDifferent = !arraysAreEqual(oldState, value);
845
+ } else if (isDescendantOf(propData.type, DataType)) {
846
+ isDifferent = !propData.type.valuesAreEqual(oldState, value);
864
847
  } else {
865
848
  isDifferent = oldState !== value;
866
849
  }
@@ -996,10 +979,13 @@ class UI5Element extends HTMLElement {
996
979
  this._generateAccessors();
997
980
  registerTag(tag);
998
981
  window.customElements.define(tag, this);
982
+ preloadLinks(this);
999
983
 
1000
984
  if (altTag && !customElements.get(altTag)) {
1001
985
  registerTag(altTag);
1002
- window.customElements.define(altTag, getClassCopy(this));
986
+ window.customElements.define(altTag, getClassCopy(this, () => {
987
+ console.log(`The ${altTag} tag is deprecated and will be removed in the next release, please use ${tag} instead.`); // eslint-disable-line
988
+ }));
1003
989
  }
1004
990
  }
1005
991
  return this;
@@ -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
  /**
@@ -212,6 +212,14 @@ class UI5ElementMetadata {
212
212
  return !!this.metadata.languageAware;
213
213
  }
214
214
 
215
+ /**
216
+ * Determines whether this UI5 Element has any theme dependant carachteristics.
217
+ * @returns {boolean}
218
+ */
219
+ isThemeAware() {
220
+ return !!this.metadata.themeAware;
221
+ }
222
+
215
223
  /**
216
224
  * Matches a changed entity (property/slot) with the given name against the "invalidateOnChildChange" configuration
217
225
  * 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 { isTheme } from "../config/Theme.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
  }
@@ -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 = _getDefaultCollection();
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 || _getDefaultCollection();
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,22 @@ 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 _getDefaultCollection = () => {
121
+ return isTheme("sap_horizon") ? "SAP-icons-v5" : "SAP-icons";
122
+ };
123
+
124
+ const _normalizeCollection = collectionName => {
125
+ if (IconCollectionsAlias[collectionName]) {
126
+ return IconCollectionsAlias[collectionName];
127
+ }
128
+
129
+ return collectionName;
130
+ };
131
+
111
132
  export {
112
133
  registerIconBundle,
113
134
  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
+ };
@@ -16,11 +16,20 @@ const M_ISO639_OLD_TO_NEW = {
16
16
  "sh": "sr",
17
17
  };
18
18
 
19
+ const DEV_MODE = false;
20
+
19
21
  const _showAssetsWarningOnce = localeId => {
20
- if (!warningShown) {
22
+ if (warningShown) {
23
+ return;
24
+ }
25
+
26
+ if (!DEV_MODE) {
21
27
  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;
28
+ } else {
29
+ 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
30
  }
31
+
32
+ warningShown = true;
24
33
  };
25
34
 
26
35
  const calcLocale = (language, region, script) => {
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Supported icon collection names and aliases.
3
+ *
4
+ * Users might specify a collection, using both the key and the value in the following key-value pairs,
5
+ * e.g the following pairs are completely exchangeable:
6
+ * "SAP-icons-TNT/actor" and "tnt/actor", "BusinessSuiteInAppSymbols/3d" and "business-suite/3d",
7
+ * "SAP-icons-v5/accept" and "horizon/accept".
8
+ *
9
+ * Note: technically, in the code we maintain the collections under the "value" name - "tnt", "business-suite",
10
+ * SAP-icons-v5" and "SAP-icons"(which does not have an alias).
11
+ */
12
+ const IconCollectionsAlias = {
13
+ "SAP-icons-TNT": "tnt",
14
+ "BusinessSuiteInAppSymbols": "business-suite",
15
+ "horizon": "SAP-icons-v5",
16
+ };
17
+
18
+ export default IconCollectionsAlias;
@@ -1,4 +1,5 @@
1
1
  import { getTheme as getConfiguredTheme } from "../InitialConfiguration.js";
2
+ import { reRenderAllUI5Elements } from "../Render.js";
2
3
  import applyTheme from "../theming/applyTheme.js";
3
4
 
4
5
  let theme;
@@ -20,9 +21,22 @@ const setTheme = async newTheme => {
20
21
 
21
22
  // Update CSS Custom Properties
22
23
  await applyTheme(theme);
24
+ await reRenderAllUI5Elements({ themeAware: true });
25
+ };
26
+
27
+ /**
28
+ * Returns if the given theme name is the one currently applied.
29
+ * @private
30
+ * @param {String}
31
+ * @returns {boolean}
32
+ */
33
+ const isTheme = _theme => {
34
+ const currentTheme = getTheme();
35
+ return currentTheme === _theme || currentTheme === `${_theme}_exp`;
23
36
  };
24
37
 
25
38
  export {
26
39
  getTheme,
27
40
  setTheme,
41
+ isTheme,
28
42
  };
@@ -0,0 +1,45 @@
1
+ @font-face {
2
+ font-family: "72";
3
+ font-style: normal;
4
+ font-weight: 400;
5
+ src: local("72"),
6
+ url(https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Regular.woff2?ui5-webcomponents) format("woff2"),
7
+ url(https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Regular.woff?ui5-webcomponents) format("woff");
8
+ }
9
+
10
+ @font-face {
11
+ font-family: "72full";
12
+ font-style: normal;
13
+ font-weight: 400;
14
+ src: local('72-full'),
15
+ url(https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Regular-full.woff2?ui5-webcomponents) format("woff2"),
16
+ url(https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Regular-full.woff?ui5-webcomponents) format("woff");
17
+
18
+ }
19
+
20
+ @font-face {
21
+ font-family: "72";
22
+ font-style: normal;
23
+ font-weight: 700;
24
+ src: local('72-Bold'),
25
+ url(https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Bold.woff2?ui5-webcomponents) format("woff2"),
26
+ url(https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Bold.woff?ui5-webcomponents) format("woff");
27
+ }
28
+
29
+ @font-face {
30
+ font-family: "72full";
31
+ font-style: normal;
32
+ font-weight: 700;
33
+ src: local('72-Bold-full'),
34
+ url(https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Bold-full.woff2?ui5-webcomponents) format("woff2"),
35
+ url(https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Bold-full.woff?ui5-webcomponents) format("woff");
36
+ }
37
+
38
+ @font-face {
39
+ font-family: "72Black";
40
+ font-style: bold;
41
+ font-weight: 900;
42
+ src: local('72Black'),
43
+ url(https://openui5nightly.hana.ondemand.com/resources/sap/ui/core/themes/sap_horizon/fonts/72-Black.woff2?ui5-webcomponents) format("woff2"),
44
+ url(https://openui5nightly.hana.ondemand.com/resources/sap/ui/core/themes/sap_horizon/fonts/72-Black.woff?ui5-webcomponents) format("woff");
45
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Some diacritics are supported by the 72 font:
3
+ * * Grave
4
+ * * Acute
5
+ * * Circumflex
6
+ * * Tilde
7
+ *
8
+ * However, the following diacritics and the combination of multiple diacritics (including the supported ones) are not supported:
9
+ * * Breve
10
+ * * Horn
11
+ * * Dot below
12
+ * * Hook above
13
+ *
14
+ *
15
+ * Override for the characters that aren't covered by the '72' font to other system fonts
16
+ *
17
+ * U+0102-0103: A and a with Breve
18
+ * U+01A0-01A1: O and o with Horn
19
+ * U+01AF-01B0: U and u with Horn
20
+ * U+1EA0-1EB7: A and a with diacritics that are not supported by the font and combination of multiple diacritics
21
+ * U+1EB8-1EC7: E and e with diacritics that are not supported by the font and combination of multiple diacritics
22
+ * U+1EC8-1ECB: I and i with diacritics that are not supported by the font and combination of multiple diacritics
23
+ * U+1ECC-1EE3: O and o with diacritics that are not supported by the font and combination of multiple diacritics
24
+ * U+1EE4-1EF1: U and u with diacritics that are not supported by the font and combination of multiple diacritics
25
+ * U+1EF4-1EF7: Y and y with diacritics that are not supported by the font and combination of multiple diacritics
26
+ *
27
+ */
28
+ @font-face {
29
+ font-family: '72override';
30
+ unicode-range: U+0102-0103, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EB7, U+1EB8-1EC7, U+1EC8-1ECB, U+1ECC-1EE3, U+1EE4-1EF1, U+1EF4-1EF7;
31
+ src: local('Arial'), local('Helvetica'), local('sans-serif');
32
+ }
@@ -0,0 +1,17 @@
1
+ :root {
2
+ --_ui5_content_density:cozy;
3
+ }
4
+
5
+ [data-ui5-compact-size],
6
+ .ui5-content-density-compact,
7
+ .sapUiSizeCompact {
8
+ --_ui5_content_density:compact;
9
+ }
10
+
11
+ [dir="rtl"] {
12
+ --_ui5_dir:rtl;
13
+ }
14
+
15
+ [dir="ltr"] {
16
+ --_ui5_dir:ltr;
17
+ }
@@ -5,6 +5,8 @@ import {
5
5
  isRight,
6
6
  isHome,
7
7
  isEnd,
8
+ isPageDown,
9
+ isPageUp,
8
10
  } from "../Keys.js";
9
11
  import getActiveElement from "../util/getActiveElement.js";
10
12
 
@@ -52,6 +54,7 @@ class ItemNavigation {
52
54
  * - currentIndex: the index of the item that will be initially selected (from which navigation will begin)
53
55
  * - navigationMode (Auto|Horizontal|Vertical): whether the items are displayed horizontally (Horizontal), vertically (Vertical) or as a matrix (Auto) meaning the user can navigate in both directions (up/down and left/right)
54
56
  * - rowSize: tells how many items per row there are when the items are not rendered as a flat list but rather as a matrix. Relevant for navigationMode=Auto
57
+ * - skipItemsSize: tells how many items upon PAGE_UP and PAGE_DOWN should be skipped to applying the focus on the next item
55
58
  * - behavior (Static|Cycling): tells what to do when trying to navigate beyond the first and last items
56
59
  * Static means that nothing happens if the user tries to navigate beyond the first/last item.
57
60
  * Cycling means that when the user navigates beyond the last item they go to the first and vice versa.
@@ -85,6 +88,7 @@ class ItemNavigation {
85
88
  this._behavior = options.behavior || ItemNavigationBehavior.Static;
86
89
  this._navigationMode = options.navigationMode || NavigationMode.Auto;
87
90
  this._affectedPropertiesNames = options.affectedPropertiesNames || [];
91
+ this._skipItemsSize = options.skipItemsSize || null;
88
92
  }
89
93
 
90
94
  /**
@@ -142,6 +146,10 @@ class ItemNavigation {
142
146
  this._handleHome();
143
147
  } else if (isEnd(event)) {
144
148
  this._handleEnd();
149
+ } else if (isPageUp(event)) {
150
+ this._handlePageUp();
151
+ } else if (isPageDown(event)) {
152
+ this._handlePageDown();
145
153
  } else {
146
154
  return; // if none of the supported keys is pressed, we don't want to prevent the event or update the item navigation
147
155
  }
@@ -222,6 +230,64 @@ class ItemNavigation {
222
230
  this._currentIndex += (homeEndRange - 1 - this._currentIndex % homeEndRange); // eslint-disable-line
223
231
  }
224
232
 
233
+ _handlePageUp() {
234
+ if (this._rowSize > 1) {
235
+ // eslint-disable-next-line
236
+ // TODO: handle page up on matrix (grid) layout - ColorPalette, ProductSwitch.
237
+ return;
238
+ }
239
+ this._handlePageUpFlat();
240
+ }
241
+
242
+ _handlePageDown() {
243
+ if (this._rowSize > 1) {
244
+ // eslint-disable-next-line
245
+ // TODO: handle page up on matrix (grid) layout - ColorPalette, ProductSwitch.
246
+ return;
247
+ }
248
+ this._handlePageDownFlat();
249
+ }
250
+
251
+ /**
252
+ * Handles PAGE_UP in a flat list-like structure, both vertically and horizontally.
253
+ */
254
+ _handlePageUpFlat() {
255
+ if (this._skipItemsSize === null) {
256
+ // Move the focus to the very top (as Home).
257
+ this._currentIndex -= this._currentIndex;
258
+ }
259
+
260
+ if (this._currentIndex + 1 > this._skipItemsSize) {
261
+ // When there are more than "skipItemsSize" number of items to the top,
262
+ // move the focus up/left with the predefined number.
263
+ this._currentIndex -= this._skipItemsSize;
264
+ } else {
265
+ // Otherwise, move the focus to the very top (as Home).
266
+ this._currentIndex -= this._currentIndex;
267
+ }
268
+ }
269
+
270
+ /**
271
+ * Handles PAGE_DOWN in a flat list-like structure, both vertically and horizontally.
272
+ */
273
+ _handlePageDownFlat() {
274
+ if (this._skipItemsSize === null) {
275
+ // Move the focus to the very bottom (as End).
276
+ this._currentIndex = this._getItems().length - 1;
277
+ }
278
+
279
+ const currentToEndRange = this._getItems().length - this._currentIndex - 1;
280
+
281
+ if (currentToEndRange > this._skipItemsSize) {
282
+ // When there are more than "skipItemsSize" number of items until the bottom,
283
+ // move the focus down/right with the predefined number.
284
+ this._currentIndex += this._skipItemsSize;
285
+ } else {
286
+ // Otherwise, move the focus to the very bottom (as End).
287
+ this._currentIndex = this._getItems().length - 1;
288
+ }
289
+ }
290
+
225
291
  _applyTabIndex() {
226
292
  const items = this._getItems();
227
293
  for (let i = 0; i < items.length; i++) {
@@ -70,7 +70,13 @@ class ScrollEnablement extends EventProvider {
70
70
  this._container.scrollTop = top;
71
71
  }
72
72
 
73
- move(dx, dy) {
73
+ move(dx, dy, disableAnimation) {
74
+ if (disableAnimation) {
75
+ this._container.scrollLeft += dx;
76
+ this._container.scrollTop += dy;
77
+ return;
78
+ }
79
+
74
80
  return scroll({
75
81
  element: this._container,
76
82
  dx,