@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
@@ -0,0 +1,80 @@
1
+ .busy-indicator-wrapper {
2
+ position: relative;
3
+ height: 100%;
4
+ width: 100%;
5
+ }
6
+
7
+ .busy-indicator-overlay {
8
+ display: var(--ui5_web_components_busy_indicator_display);
9
+ position: absolute;
10
+ inset: 0;
11
+ background: var(--ui5_web_components_busy_indicator_background-color);
12
+ z-index: 99;
13
+ }
14
+
15
+ .busy-indicator-busy-area {
16
+ display: var(--ui5_web_components_busy_indicator_display);
17
+ position: absolute;
18
+ z-index: 99;
19
+ inset: 0;
20
+ justify-content: center;
21
+ align-items: center;
22
+ background-color: inherit;
23
+ flex-direction: column;
24
+ color: var(--_ui5_busy_indicator_color);
25
+ }
26
+
27
+ :host([__is-busy]) .busy-indicator-wrapper > :not(.busy-indicator-busy-area):not(.busy-indicator-overlay):not([busy-indicator-before-span]) {
28
+ --ui5_web_components_busy_indicator_display: none;
29
+ }
30
+
31
+ .busy-indicator-busy-area:focus {
32
+ outline: var(--_ui5_busy_indicator_focus_outline);
33
+ outline-offset: -.125rem;
34
+ }
35
+
36
+ .busy-indicator-circle {
37
+ width: 1rem;
38
+ height: 1rem;
39
+ display: inline-block;
40
+ background-color: currentColor;
41
+ border-radius: 50%;
42
+ }
43
+
44
+ .circle-animation-0 {
45
+ animation: grow 1.6s infinite cubic-bezier(0.32, 0.06, 0.85, 1.11);
46
+ }
47
+
48
+ .circle-animation-1 {
49
+ animation: grow 1.6s infinite cubic-bezier(0.32, 0.06, 0.85, 1.11);
50
+ animation-delay: 200ms;
51
+ }
52
+
53
+ .circle-animation-2 {
54
+ animation: grow 1.6s infinite cubic-bezier(0.32, 0.06, 0.85, 1.11);
55
+ animation-delay: 400ms;
56
+ }
57
+
58
+ .sapUiLocalBusy {
59
+ --ui5_web_components_busy_indicator_display: none;
60
+ }
61
+
62
+ .busy-indicator-wrapper [ui5-busy-indicator] {
63
+ display: none;
64
+ }
65
+
66
+ @keyframes grow {
67
+ 0%, 50%, 100% {
68
+ -webkit-transform: scale(0.5);
69
+ -moz-transform: scale(0.5);
70
+ -ms-transform: scale(0.5);
71
+ transform: scale(0.5);
72
+ }
73
+
74
+ 25% {
75
+ -webkit-transform: scale(1);
76
+ -moz-transform: scale(1);
77
+ -ms-transform: scale(1);
78
+ transform: scale(1);
79
+ }
80
+ }
@@ -0,0 +1,75 @@
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/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Regular.woff2?ui5-webcomponents) format("woff2"),
7
+ url(https://ui5.sap.com/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/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Regular-full.woff2?ui5-webcomponents) format("woff2"),
16
+ url(https://ui5.sap.com/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/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Bold.woff2?ui5-webcomponents) format("woff2"),
26
+ url(https://ui5.sap.com/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/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Bold-full.woff2?ui5-webcomponents) format("woff2"),
35
+ url(https://ui5.sap.com/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: '72-Bold';
40
+ font-style: normal;
41
+ src: local('72-Bold'),
42
+ url(https://ui5.sap.com/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Bold.woff2?ui5-webcomponents) format("woff2"),
43
+ url(https://ui5.sap.com/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Bold.woff?ui5-webcomponents) format("woff");
44
+ }
45
+
46
+ @font-face {
47
+ font-family: '72-Boldfull';
48
+ font-style: normal;
49
+ src: url(https://ui5.sap.com/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Bold-full.woff2?ui5-webcomponents) format("woff2"),
50
+ url(https://ui5.sap.com/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Bold-full.woff?ui5-webcomponents) format("woff");
51
+ }
52
+
53
+ @font-face {
54
+ font-family: '72-Light';
55
+ font-style: normal;
56
+ src: local('72-Light'),
57
+ url(https://ui5.sap.com/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Light.woff2?ui5-webcomponents) format("woff2"),
58
+ url(https://ui5.sap.com/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Light.woff?ui5-webcomponents) format("woff");
59
+ }
60
+
61
+ @font-face {
62
+ font-family: '72-Lightfull';
63
+ font-style: normal;
64
+ src: url(https://ui5.sap.com/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Light-full.woff2?ui5-webcomponents) format("woff2"),
65
+ url(https://ui5.sap.com/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Light-full.woff?ui5-webcomponents) format("woff");
66
+ }
67
+
68
+ @font-face {
69
+ font-family: "72Black";
70
+ font-style: bold;
71
+ font-weight: 900;
72
+ src: local('72Black'),
73
+ url(https://openui5nightly.hana.ondemand.com/resources/sap/ui/core/themes/sap_horizon/fonts/72-Black.woff2?ui5-webcomponents) format("woff2"),
74
+ url(https://openui5nightly.hana.ondemand.com/resources/sap/ui/core/themes/sap_horizon/fonts/72-Black.woff?ui5-webcomponents) format("woff");
75
+ }
@@ -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
  /**
@@ -129,19 +133,28 @@ class ItemNavigation {
129
133
 
130
134
  const horizontalNavigationOn = this._navigationMode === NavigationMode.Horizontal || this._navigationMode === NavigationMode.Auto;
131
135
  const verticalNavigationOn = this._navigationMode === NavigationMode.Vertical || this._navigationMode === NavigationMode.Auto;
136
+ const isRTL = this.rootWebComponent.effectiveDir === "rtl";
132
137
 
133
- if (isUp(event) && verticalNavigationOn) {
134
- this._handleUp();
135
- } else if (isDown(event) && verticalNavigationOn) {
136
- this._handleDown();
138
+ if (isRTL && isLeft(event) && horizontalNavigationOn) {
139
+ this._handleRight();
140
+ } else if (isRTL && isRight(event) && horizontalNavigationOn) {
141
+ this._handleLeft();
137
142
  } else if (isLeft(event) && horizontalNavigationOn) {
138
143
  this._handleLeft();
139
144
  } else if (isRight(event) && horizontalNavigationOn) {
140
145
  this._handleRight();
146
+ } else if (isUp(event) && verticalNavigationOn) {
147
+ this._handleUp();
148
+ } else if (isDown(event) && verticalNavigationOn) {
149
+ this._handleDown();
141
150
  } else if (isHome(event)) {
142
151
  this._handleHome();
143
152
  } else if (isEnd(event)) {
144
153
  this._handleEnd();
154
+ } else if (isPageUp(event)) {
155
+ this._handlePageUp();
156
+ } else if (isPageDown(event)) {
157
+ this._handlePageDown();
145
158
  } else {
146
159
  return; // if none of the supported keys is pressed, we don't want to prevent the event or update the item navigation
147
160
  }
@@ -222,6 +235,64 @@ class ItemNavigation {
222
235
  this._currentIndex += (homeEndRange - 1 - this._currentIndex % homeEndRange); // eslint-disable-line
223
236
  }
224
237
 
238
+ _handlePageUp() {
239
+ if (this._rowSize > 1) {
240
+ // eslint-disable-next-line
241
+ // TODO: handle page up on matrix (grid) layout - ColorPalette, ProductSwitch.
242
+ return;
243
+ }
244
+ this._handlePageUpFlat();
245
+ }
246
+
247
+ _handlePageDown() {
248
+ if (this._rowSize > 1) {
249
+ // eslint-disable-next-line
250
+ // TODO: handle page up on matrix (grid) layout - ColorPalette, ProductSwitch.
251
+ return;
252
+ }
253
+ this._handlePageDownFlat();
254
+ }
255
+
256
+ /**
257
+ * Handles PAGE_UP in a flat list-like structure, both vertically and horizontally.
258
+ */
259
+ _handlePageUpFlat() {
260
+ if (this._skipItemsSize === null) {
261
+ // Move the focus to the very top (as Home).
262
+ this._currentIndex -= this._currentIndex;
263
+ }
264
+
265
+ if (this._currentIndex + 1 > this._skipItemsSize) {
266
+ // When there are more than "skipItemsSize" number of items to the top,
267
+ // move the focus up/left with the predefined number.
268
+ this._currentIndex -= this._skipItemsSize;
269
+ } else {
270
+ // Otherwise, move the focus to the very top (as Home).
271
+ this._currentIndex -= this._currentIndex;
272
+ }
273
+ }
274
+
275
+ /**
276
+ * Handles PAGE_DOWN in a flat list-like structure, both vertically and horizontally.
277
+ */
278
+ _handlePageDownFlat() {
279
+ if (this._skipItemsSize === null) {
280
+ // Move the focus to the very bottom (as End).
281
+ this._currentIndex = this._getItems().length - 1;
282
+ }
283
+
284
+ const currentToEndRange = this._getItems().length - this._currentIndex - 1;
285
+
286
+ if (currentToEndRange > this._skipItemsSize) {
287
+ // When there are more than "skipItemsSize" number of items until the bottom,
288
+ // move the focus down/right with the predefined number.
289
+ this._currentIndex += this._skipItemsSize;
290
+ } else {
291
+ // Otherwise, move the focus to the very bottom (as End).
292
+ this._currentIndex = this._getItems().length - 1;
293
+ }
294
+ }
295
+
225
296
  _applyTabIndex() {
226
297
  const items = this._getItems();
227
298
  for (let i = 0; i < items.length; i++) {
@@ -0,0 +1,110 @@
1
+ import { registerFeature } from "../FeaturesRegistry.js";
2
+ import { isF6Next, isF6Previous } from "../Keys.js";
3
+ import { getFirstFocusableElement } from "../util/FocusableElements.js";
4
+
5
+ class F6Navigation {
6
+ init() {
7
+ this.keydownHandler = this._keydownHandler.bind(this);
8
+ this.attachEventListeners();
9
+ this.selectedGroup = null;
10
+ this.groups = [];
11
+ }
12
+
13
+ attachEventListeners() {
14
+ document.addEventListener("keydown", this.keydownHandler);
15
+ }
16
+
17
+ async _keydownHandler(event) {
18
+ if (isF6Next(event)) {
19
+ this.updateGroups();
20
+ if (this.groups.length < 1) {
21
+ return;
22
+ }
23
+
24
+ event.preventDefault();
25
+
26
+ const nextIndex = this.groups.indexOf(this.selectedGroup);
27
+ let nextElement = null;
28
+
29
+ if (nextIndex > -1) {
30
+ if (nextIndex + 1 >= this.groups.length) {
31
+ nextElement = this.groups[0];
32
+ } else {
33
+ nextElement = this.groups[nextIndex + 1];
34
+ }
35
+ } else {
36
+ nextElement = this.groups[0];
37
+ }
38
+
39
+ const elementToFocus = await getFirstFocusableElement(nextElement.isUI5Element ? nextElement.getDomRef() : nextElement, true);
40
+ elementToFocus.focus();
41
+ }
42
+
43
+ if (isF6Previous(event)) {
44
+ this.updateGroups();
45
+ if (this.groups.length < 1) {
46
+ return;
47
+ }
48
+
49
+ event.preventDefault();
50
+
51
+ const nextIndex = this.groups.indexOf(this.selectedGroup);
52
+ let nextElement = null;
53
+
54
+ if (nextIndex > -1) {
55
+ if (nextIndex - 1 < 0) {
56
+ nextElement = this.groups[this.groups.length - 1];
57
+ } else {
58
+ // Handle the situation where the first focusable element of two neighbor groups is the same
59
+ // For example:
60
+ // <ui5-flexible-column-layout>
61
+ // <ui5-list>
62
+ // <ui5-li>List Item</ui5-li>
63
+ // </ui5-list>
64
+ // </ui5-flexible-column-layout>
65
+ // Here for both FCL & List the firstFoccusableElement is the same (the ui5-li)
66
+
67
+ const firstFocusable = await getFirstFocusableElement(this.groups[nextIndex - 1], true);
68
+ const shouldSkipParent = firstFocusable === await getFirstFocusableElement(this.groups[nextIndex], true);
69
+
70
+ nextElement = this.groups[shouldSkipParent ? nextIndex - 2 : nextIndex - 1];
71
+ }
72
+ } else {
73
+ nextElement = this.groups[this.groups.length - 1];
74
+ }
75
+
76
+ const elementToFocus = await getFirstFocusableElement(nextElement.isUI5Element ? nextElement.getDomRef() : nextElement, true);
77
+ elementToFocus.focus();
78
+ }
79
+ }
80
+
81
+ removeEventListeners() {
82
+ document.removeEventListener("keydown", this.keydownHandler);
83
+ }
84
+
85
+ updateGroups() {
86
+ this.setSelectedGroup(document.activeElement);
87
+ this.setGroups();
88
+ }
89
+
90
+ setGroups() {
91
+ this.groups = Array.from(document.querySelectorAll("[data-sap-ui-fastnavgroup='true']")).filter(group => group.clientWidth && window.getComputedStyle(group).visibility !== "hidden");
92
+ }
93
+
94
+ setSelectedGroup(element) {
95
+ while (element && element.getAttribute("data-sap-ui-fastnavgroup") !== "true" && element !== document.querySelector("html")) {
96
+ element = element.parentElement ? element.parentNode : element.parentNode.host;
97
+ }
98
+
99
+ this.selectedGroup = element;
100
+ }
101
+
102
+ destroy() {
103
+ this.removeEventListeners();
104
+ }
105
+ }
106
+
107
+ const F6HelperInstance = new F6Navigation();
108
+ registerFeature("F6Navigation", F6HelperInstance);
109
+
110
+ export default F6Navigation;
@@ -0,0 +1,119 @@
1
+ import { registerFeature } from "../FeaturesRegistry.js";
2
+ import BusyIndicatorStyles from "../generated/css/BusyIndicator.css.js";
3
+ import merge from "../thirdparty/merge.js";
4
+ import {
5
+ isTabPrevious,
6
+ } from "../Keys.js";
7
+
8
+ const busyIndicatorMetadata = {
9
+ properties: {
10
+ __isBusy: {
11
+ type: Boolean,
12
+ },
13
+ },
14
+ };
15
+
16
+ const getBusyIndicatorStyles = () => {
17
+ return BusyIndicatorStyles;
18
+ };
19
+
20
+ const wrapTemplateResultInBusyMarkup = (html, host, templateResult) => {
21
+ if (host.isOpenUI5Component && host.__isBusy) {
22
+ templateResult = html`
23
+ <div class="busy-indicator-wrapper">
24
+ <span tabindex="0" busy-indicator-before-span @focusin=${host.__suppressFocusIn}></span>
25
+ ${templateResult}
26
+ <div class="busy-indicator-overlay"></div>
27
+ <div busy-indicator
28
+ class="busy-indicator-busy-area"
29
+ tabindex="0"
30
+ role="progressbar"
31
+ @keydown=${host.__suppressFocusBack}
32
+ aria-valuemin="0"
33
+ aria-valuemax="100"
34
+ aria-valuetext="Busy">
35
+ <div>
36
+ <div class="busy-indicator-circle circle-animation-0"></div>
37
+ <div class="busy-indicator-circle circle-animation-1"></div>
38
+ <div class="busy-indicator-circle circle-animation-2"></div>
39
+ </div>
40
+ </div>
41
+ </div>`;
42
+ }
43
+
44
+ return templateResult;
45
+ };
46
+
47
+ const enrichBusyIndicatorMetadata = UI5Element => {
48
+ UI5Element.metadata = merge(UI5Element.metadata, busyIndicatorMetadata);
49
+ };
50
+
51
+ const enrichBusyIndicatorMethods = UI5ElementPrototype => {
52
+ Object.defineProperties(UI5ElementPrototype, {
53
+ "__redirectFocus": { value: true, writable: true },
54
+ "__suppressFocusBack": {
55
+ get() {
56
+ const that = this;
57
+
58
+ return {
59
+ handleEvent: e => {
60
+ if (isTabPrevious(e)) {
61
+ const beforeElem = that.shadowRoot.querySelector("[busy-indicator-before-span]");
62
+ that.__redirectFocus = false;
63
+ beforeElem.focus();
64
+ that.__redirectFocus = true;
65
+ }
66
+ },
67
+ capture: true,
68
+ passive: false,
69
+ };
70
+ },
71
+ },
72
+ "isOpenUI5Component": { get: () => { return true; } },
73
+ });
74
+
75
+ UI5ElementPrototype.__suppressFocusIn = function handleFocusIn() {
76
+ const busyIndicator = this.shadowRoot.querySelector("[busy-indicator]");
77
+ if (busyIndicator && this.__redirectFocus) {
78
+ busyIndicator.focus();
79
+ }
80
+ };
81
+
82
+ UI5ElementPrototype.getDomRef = function getDomRef() {
83
+ // If a component set _getRealDomRef to its children, use the return value of this function
84
+ if (typeof this._getRealDomRef === "function") {
85
+ return this._getRealDomRef();
86
+ }
87
+
88
+ if (!this.shadowRoot || this.shadowRoot.children.length === 0) {
89
+ return;
90
+ }
91
+
92
+ const children = [...this.shadowRoot.children].filter(child => !["link", "style"].includes(child.localName));
93
+
94
+ if (children.length !== 1) {
95
+ 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
96
+ }
97
+
98
+ if (this.__isBusy) {
99
+ return children[0].querySelector(".busy-indicator-wrapper > :not([busy-indicator-before-span]):not(.busy-indicator-overlay):not(.busy-indicator-busy-area)");
100
+ }
101
+
102
+ return children[0];
103
+ };
104
+ };
105
+
106
+ const enrichBusyIndicatorSettings = UI5Element => {
107
+ enrichBusyIndicatorMetadata(UI5Element);
108
+ enrichBusyIndicatorMethods(UI5Element.prototype);
109
+ };
110
+
111
+ const OpenUI5Enablement = {
112
+ enrichBusyIndicatorSettings,
113
+ wrapTemplateResultInBusyMarkup,
114
+ getBusyIndicatorStyles,
115
+ };
116
+
117
+ export default OpenUI5Enablement;
118
+
119
+ registerFeature("OpenUI5Enablement", OpenUI5Enablement);
package/src/i18nBundle.js CHANGED
@@ -3,6 +3,8 @@ import formatMessage from "./util/formatMessage.js";
3
3
 
4
4
  const I18nBundleInstances = new Map();
5
5
 
6
+ let customGetI18nBundle;
7
+
6
8
  /**
7
9
  * @class
8
10
  * @public
@@ -15,6 +17,7 @@ class I18nBundle {
15
17
  /**
16
18
  * Returns a text in the currently loaded language
17
19
  *
20
+ * @public
18
21
  * @param {Object|String} textObj key/defaultText pair or just the key
19
22
  * @param params Values for the placeholders
20
23
  * @returns {*}
@@ -38,7 +41,7 @@ class I18nBundle {
38
41
  }
39
42
  }
40
43
 
41
- const getI18nBundle = packageName => {
44
+ const getI18nBundleSync = packageName => {
42
45
  if (I18nBundleInstances.has(packageName)) {
43
46
  return I18nBundleInstances.get(packageName);
44
47
  }
@@ -48,8 +51,36 @@ const getI18nBundle = packageName => {
48
51
  return i18nBundle;
49
52
  };
50
53
 
54
+ /**
55
+ * Allows developers to provide a custom getI18nBundle implementation
56
+ * If this function is called, the custom implementation will be used for all components and will completely
57
+ * replace the default implementation.
58
+ *
59
+ * @public
60
+ * @param customGet the function to use instead of the standard getI18nBundle implementation
61
+ */
62
+ const registerCustomI18nBundleGetter = customGet => {
63
+ customGetI18nBundle = customGet;
64
+ };
65
+
66
+ /**
67
+ * Fetches and returns the I18nBundle instance for the given package
68
+ *
69
+ * @public
70
+ * @param packageName
71
+ * @returns {Promise<I18nBundle>}
72
+ */
73
+ const getI18nBundle = async packageName => {
74
+ if (customGetI18nBundle) {
75
+ return customGetI18nBundle(packageName);
76
+ }
77
+
78
+ await fetchI18nBundle(packageName);
79
+ return getI18nBundleSync(packageName);
80
+ };
81
+
51
82
  export {
52
83
  registerI18nLoader,
53
- fetchI18nBundle,
54
84
  getI18nBundle,
85
+ registerCustomI18nBundleGetter,
55
86
  };
@@ -1,31 +1,52 @@
1
- import { render } from "lit-html";
2
1
  import {
2
+ render,
3
3
  html,
4
4
  svg,
5
- unsafeStatic,
6
- } from "lit-html/static.js";
5
+ } from "lit-html";
6
+ import { getFeature } from "../FeaturesRegistry.js";
7
7
 
8
- const litRender = (templateResult, domNode, styles, { host } = {}) => {
9
- if (styles) {
10
- templateResult = html`<style>${styles}</style>${templateResult}`;
8
+ const effectiveHtml = (...args) => {
9
+ const LitStatic = getFeature("LitStatic");
10
+ const fn = LitStatic ? LitStatic.html : html;
11
+ return fn(...args);
12
+ };
13
+
14
+ const effectiveSvg = (...args) => {
15
+ const LitStatic = getFeature("LitStatic");
16
+ const fn = LitStatic ? LitStatic.svg : svg;
17
+ return fn(...args);
18
+ };
19
+
20
+ const litRender = (templateResult, domNode, styleStrOrHrefsArr, forStaticArea, { host } = {}) => {
21
+ const OpenUI5Enablement = getFeature("OpenUI5Enablement");
22
+ if (OpenUI5Enablement && !forStaticArea) {
23
+ templateResult = OpenUI5Enablement.wrapTemplateResultInBusyMarkup(effectiveHtml, host, templateResult);
24
+ }
25
+
26
+ if (typeof styleStrOrHrefsArr === "string") {
27
+ templateResult = effectiveHtml`<style>${styleStrOrHrefsArr}</style>${templateResult}`;
28
+ } else if (Array.isArray(styleStrOrHrefsArr) && styleStrOrHrefsArr.length) {
29
+ templateResult = effectiveHtml`${styleStrOrHrefsArr.map(href => effectiveHtml`<link type="text/css" rel="stylesheet" href="${href}">`)}${templateResult}`;
11
30
  }
12
31
  render(templateResult, domNode, { host });
13
32
  };
14
33
 
15
34
  const scopeTag = (tag, tags, suffix) => {
16
- const resultTag = suffix && (tags || []).includes(tag) ? `${tag}-${suffix}` : tag;
17
- return unsafeStatic(resultTag);
35
+ const LitStatic = getFeature("LitStatic");
36
+ if (LitStatic) {
37
+ return LitStatic.unsafeStatic((tags || []).includes(tag) ? `${tag}-${suffix}` : tag);
38
+ }
18
39
  };
19
40
 
20
41
  export {
21
- html,
22
- svg,
23
- unsafeStatic,
42
+ effectiveHtml as html,
43
+ effectiveSvg as svg,
24
44
  };
25
45
  export { scopeTag };
26
46
  export { repeat } from "lit-html/directives/repeat.js";
27
47
  export { classMap } from "lit-html/directives/class-map.js";
28
- export { styleMap } from "lit-html/directives/style-map.js";
48
+ export { styleMap } from "./directives/style-map.js";
49
+ export { ifDefined } from "lit-html/directives/if-defined.js";
29
50
  export { unsafeHTML } from "lit-html/directives/unsafe-html.js";
30
51
 
31
52
  export default litRender;