@ui5/webcomponents-base 0.0.0-b4cbc43ba → 0.0.0-b93c2a321

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 (212) hide show
  1. package/.eslintignore +3 -0
  2. package/CHANGELOG.md +214 -0
  3. package/README.md +26 -2
  4. package/bundle.esm.js +10 -7
  5. package/dist/AssetRegistry.js +8 -9
  6. package/dist/Boot.js +17 -6
  7. package/dist/CSP.js +59 -0
  8. package/dist/CustomElementsRegistry.js +60 -4
  9. package/dist/CustomElementsScope.js +20 -98
  10. package/dist/CustomElementsScopeUtils.js +108 -0
  11. package/dist/DOMObserver.js +6 -2
  12. package/dist/Device.js +69 -776
  13. package/dist/EventProvider.js +19 -25
  14. package/dist/FeaturesRegistry.js +4 -1
  15. package/dist/FontFace.js +7 -95
  16. package/dist/InitialConfiguration.js +37 -21
  17. package/dist/Keys.js +74 -0
  18. package/dist/ManagedStyles.js +83 -0
  19. package/dist/MediaRange.js +109 -0
  20. package/dist/{util/parseProperties.js → PropertiesFileFormat.js} +6 -0
  21. package/dist/Render.js +3 -2
  22. package/dist/Runtimes.js +107 -0
  23. package/dist/StaticArea.js +3 -0
  24. package/dist/StaticAreaItem.js +31 -10
  25. package/dist/SystemCSSVars.js +4 -25
  26. package/dist/UI5Element.js +66 -65
  27. package/dist/UI5ElementMetadata.js +18 -2
  28. package/dist/asset-registries/Icons.js +117 -14
  29. package/dist/asset-registries/Illustrations.js +30 -0
  30. package/dist/asset-registries/LocaleData.js +97 -68
  31. package/dist/asset-registries/Themes.js +23 -33
  32. package/dist/asset-registries/i18n.js +61 -50
  33. package/dist/assets-meta/IconCollectionsAlias.js +18 -0
  34. package/dist/config/Icons.js +52 -0
  35. package/dist/config/Language.js +15 -15
  36. package/dist/config/Theme.js +25 -0
  37. package/dist/css/BusyIndicator.css +76 -0
  38. package/dist/css/FontFace.css +75 -0
  39. package/dist/css/OverrideFontFace.css +32 -0
  40. package/dist/css/SystemCSSVars.css +17 -0
  41. package/dist/delegate/ItemNavigation.js +163 -105
  42. package/dist/delegate/ScrollEnablement.js +25 -19
  43. package/dist/features/F6Navigation.js +108 -0
  44. package/dist/features/OpenUI5Enablement.js +119 -0
  45. package/dist/features/OpenUI5Support.js +41 -6
  46. package/dist/generated/AssetParameters.js +1 -1
  47. package/dist/generated/VersionInfo.js +10 -0
  48. package/dist/generated/css/BusyIndicator.css.js +5 -0
  49. package/dist/generated/css/FontFace.css.js +5 -0
  50. package/dist/generated/css/OverrideFontFace.css.js +5 -0
  51. package/dist/generated/css/SystemCSSVars.css.js +5 -0
  52. package/dist/i18nBundle.js +38 -4
  53. package/dist/renderer/LitRenderer.js +39 -18
  54. package/dist/renderer/directives/style-map.js +72 -0
  55. package/dist/renderer/executeTemplate.js +19 -2
  56. package/dist/resources/bundle.esm.js +15 -104
  57. package/dist/resources/bundle.esm.js.map +1 -1
  58. package/dist/sap/base/Log.js +241 -0
  59. package/dist/sap/base/assert.js +8 -0
  60. package/dist/sap/base/security/URLListValidator.js +148 -0
  61. package/dist/sap/base/security/encodeCSS.js +14 -0
  62. package/dist/sap/base/security/encodeXML.js +23 -0
  63. package/dist/sap/base/security/sanitizeHTML.js +16 -0
  64. package/dist/sap/base/strings/toHex.js +8 -0
  65. package/dist/sap/base/util/now.js +7 -0
  66. package/dist/sap/ui/thirdparty/caja-html-sanitizer.js +3585 -0
  67. package/dist/test-resources/assets/Themes.js +8 -8
  68. package/dist/test-resources/elements/WithStaticArea.js +2 -1
  69. package/dist/test-resources/pages/AllTestElements.html +3 -0
  70. package/dist/test-resources/pages/i18n.html +2 -9
  71. package/dist/test-resources/specs/ConfigurationChange.spec.js +10 -8
  72. package/dist/test-resources/specs/ConfigurationScript.spec.js +25 -23
  73. package/dist/test-resources/specs/ConfigurationURL.spec.js +65 -17
  74. package/dist/test-resources/specs/CustomTheme.spec.js +9 -7
  75. package/dist/test-resources/specs/EventProvider.spec.js +63 -0
  76. package/dist/test-resources/specs/StaticArea.spec.js +56 -12
  77. package/dist/test-resources/specs/Theming.spec.js +12 -10
  78. package/dist/test-resources/specs/UI5ElementInvalidation.js +30 -28
  79. package/dist/test-resources/specs/UI5ElementLifecycle.js +12 -10
  80. package/dist/test-resources/specs/UI5ElementListenForChildPropChanges.spec.js +12 -10
  81. package/dist/test-resources/specs/UI5ElementMetadataExt.js +9 -7
  82. package/dist/test-resources/specs/UI5ElementPropertyValidation.js +7 -5
  83. package/dist/test-resources/specs/UI5ElementPropsAndAttrs.spec.js +37 -35
  84. package/dist/test-resources/specs/UI5ElementShadowDOM.js +10 -8
  85. package/dist/test-resources/specs/UI5ElementSlots.js +10 -8
  86. package/dist/theming/CustomStyle.js +23 -3
  87. package/dist/theming/applyTheme.js +11 -10
  88. package/dist/theming/getEffectiveLinksHrefs.js +27 -0
  89. package/dist/theming/getEffectiveStyle.js +9 -0
  90. package/dist/theming/getStylesString.js +4 -2
  91. package/dist/theming/getThemeDesignerTheme.js +25 -5
  92. package/dist/theming/preloadLinks.js +23 -0
  93. package/dist/types/CSSColor.js +9 -0
  94. package/dist/types/DataType.js +12 -0
  95. package/dist/types/Float.js +4 -0
  96. package/dist/types/Integer.js +4 -0
  97. package/dist/types/InvisibleMessageMode.js +30 -0
  98. package/dist/updateShadowRoot.js +8 -4
  99. package/dist/util/AriaLabelHelper.js +4 -4
  100. package/dist/util/ColorConversion.js +370 -0
  101. package/dist/util/FocusableElements.js +13 -7
  102. package/dist/util/HTMLSanitizer.js +7 -0
  103. package/dist/util/InvisibleMessage.js +60 -0
  104. package/dist/util/PopupUtils.js +93 -0
  105. package/dist/util/TabbableElements.js +5 -1
  106. package/dist/util/clamp.js +12 -0
  107. package/dist/util/createLinkInHead.js +19 -0
  108. package/dist/util/escapeRegex.js +10 -0
  109. package/dist/util/generateHighlightedMarkup.js +42 -0
  110. package/dist/util/getClassCopy.js +10 -0
  111. package/dist/util/getNormalizedTarget.js +16 -0
  112. package/dist/util/isElementInView.js +15 -0
  113. package/dist/util/isNodeHidden.js +1 -1
  114. package/dist/util/isNodeTabbable.js +4 -4
  115. package/hash.txt +1 -0
  116. package/index.js +1 -1
  117. package/lib/generate-asset-parameters/index.js +0 -1
  118. package/lib/generate-styles/index.js +18 -0
  119. package/lib/generate-version-info/index.js +27 -0
  120. package/package-scripts.js +31 -15
  121. package/package.json +19 -10
  122. package/src/AssetRegistry.js +8 -9
  123. package/src/Boot.js +17 -6
  124. package/src/CSP.js +59 -0
  125. package/src/CustomElementsRegistry.js +60 -4
  126. package/src/CustomElementsScope.js +20 -98
  127. package/src/CustomElementsScopeUtils.js +108 -0
  128. package/src/DOMObserver.js +6 -2
  129. package/src/Device.js +69 -776
  130. package/src/EventProvider.js +19 -25
  131. package/src/FeaturesRegistry.js +4 -1
  132. package/src/FontFace.js +7 -95
  133. package/src/InitialConfiguration.js +37 -21
  134. package/src/Keys.js +74 -0
  135. package/src/ManagedStyles.js +83 -0
  136. package/src/MediaRange.js +109 -0
  137. package/src/{util/parseProperties.js → PropertiesFileFormat.js} +6 -0
  138. package/src/Render.js +3 -2
  139. package/src/Runtimes.js +107 -0
  140. package/src/StaticArea.js +3 -0
  141. package/src/StaticAreaItem.js +31 -10
  142. package/src/SystemCSSVars.js +4 -25
  143. package/src/UI5Element.js +66 -65
  144. package/src/UI5ElementMetadata.js +18 -2
  145. package/src/asset-registries/Icons.js +117 -14
  146. package/src/asset-registries/Illustrations.js +30 -0
  147. package/src/asset-registries/LocaleData.js +97 -68
  148. package/src/asset-registries/Themes.js +23 -33
  149. package/src/asset-registries/i18n.js +61 -50
  150. package/src/assets-meta/IconCollectionsAlias.js +18 -0
  151. package/src/config/Icons.js +52 -0
  152. package/src/config/Language.js +15 -15
  153. package/src/config/Theme.js +25 -0
  154. package/src/css/BusyIndicator.css +76 -0
  155. package/src/css/FontFace.css +75 -0
  156. package/src/css/OverrideFontFace.css +32 -0
  157. package/src/css/SystemCSSVars.css +17 -0
  158. package/src/delegate/ItemNavigation.js +163 -105
  159. package/src/delegate/ScrollEnablement.js +25 -19
  160. package/src/features/F6Navigation.js +108 -0
  161. package/src/features/OpenUI5Enablement.js +119 -0
  162. package/src/features/OpenUI5Support.js +41 -6
  163. package/src/i18nBundle.js +38 -4
  164. package/src/renderer/LitRenderer.js +39 -18
  165. package/src/renderer/directives/style-map.js +72 -0
  166. package/src/renderer/executeTemplate.js +19 -2
  167. package/src/theming/CustomStyle.js +23 -3
  168. package/src/theming/applyTheme.js +11 -10
  169. package/src/theming/getEffectiveLinksHrefs.js +27 -0
  170. package/src/theming/getEffectiveStyle.js +9 -0
  171. package/src/theming/getStylesString.js +4 -2
  172. package/src/theming/getThemeDesignerTheme.js +25 -5
  173. package/src/theming/preloadLinks.js +23 -0
  174. package/src/types/CSSColor.js +9 -0
  175. package/src/types/DataType.js +12 -0
  176. package/src/types/Float.js +4 -0
  177. package/src/types/Integer.js +4 -0
  178. package/src/types/InvisibleMessageMode.js +30 -0
  179. package/src/updateShadowRoot.js +8 -4
  180. package/src/util/AriaLabelHelper.js +4 -4
  181. package/src/util/ColorConversion.js +370 -0
  182. package/src/util/FocusableElements.js +13 -7
  183. package/src/util/HTMLSanitizer.js +7 -0
  184. package/src/util/InvisibleMessage.js +60 -0
  185. package/src/util/PopupUtils.js +93 -0
  186. package/src/util/TabbableElements.js +5 -1
  187. package/src/util/clamp.js +12 -0
  188. package/src/util/createLinkInHead.js +19 -0
  189. package/src/util/escapeRegex.js +10 -0
  190. package/src/util/generateHighlightedMarkup.js +42 -0
  191. package/src/util/getClassCopy.js +10 -0
  192. package/src/util/getNormalizedTarget.js +16 -0
  193. package/src/util/isElementInView.js +15 -0
  194. package/src/util/isNodeHidden.js +1 -1
  195. package/src/util/isNodeTabbable.js +4 -4
  196. package/used-modules.txt +10 -0
  197. package/dist/SVGIconRegistry.js +0 -73
  198. package/dist/config/AssetsPath.js +0 -17
  199. package/dist/features/PropertiesFormatSupport.js +0 -8
  200. package/dist/renderer/ifDefined.js +0 -21
  201. package/dist/renderer/scopeHTML.js +0 -32
  202. package/dist/theming/createThemePropertiesStyleTag.js +0 -20
  203. package/dist/util/EffectiveAssetPath.js +0 -27
  204. package/dist/util/encodeCSS.js +0 -24
  205. package/src/SVGIconRegistry.js +0 -73
  206. package/src/config/AssetsPath.js +0 -17
  207. package/src/features/PropertiesFormatSupport.js +0 -8
  208. package/src/renderer/ifDefined.js +0 -21
  209. package/src/renderer/scopeHTML.js +0 -32
  210. package/src/theming/createThemePropertiesStyleTag.js +0 -20
  211. package/src/util/EffectiveAssetPath.js +0 -27
  212. package/src/util/encodeCSS.js +0 -24
@@ -1,22 +1,37 @@
1
- import { registerIcon, registerCollectionPromise } from "../SVGIconRegistry.js";
2
- import { fetchJsonOnce } from "../util/FetchHelper.js";
3
- import { getEffectiveAssetPath } from "../util/EffectiveAssetPath.js";
1
+ import getSharedResource from "../getSharedResource.js";
2
+ import IconCollectionsAlias from "../assets-meta/IconCollectionsAlias.js";
3
+ import { getEffectiveDefaultIconCollection } from "../config/Icons.js";
4
4
 
5
+ const loaders = new Map();
6
+ const registry = getSharedResource("SVGIcons.registry", new Map());
7
+ const iconCollectionPromises = getSharedResource("SVGIcons.promises", new Map());
8
+
9
+ const ICON_NOT_FOUND = "ICON_NOT_FOUND";
10
+
11
+ /**
12
+ * @deprecated
13
+ */
5
14
  const registerIconBundle = async (collectionName, bundleData) => {
6
- let resolveFn;
7
- const collectionFetched = new Promise(resolve => {
8
- resolveFn = resolve;
9
- });
10
- registerCollectionPromise(collectionName, collectionFetched);
15
+ throw new Error("This method has been removed. Use `registerIconLoader` instead.");
16
+ };
11
17
 
12
- if (typeof bundleData !== "object") { // not inlined from build -> fetch it
13
- bundleData = await fetchJsonOnce(getEffectiveAssetPath(bundleData));
18
+ const registerIconLoader = async (collectionName, loader) => {
19
+ loaders.set(collectionName, loader);
20
+ };
21
+
22
+ const _loadIconCollectionOnce = async collectionName => {
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
+ }
27
+ const loadIcons = loaders.get(collectionName);
28
+ iconCollectionPromises.set(collectionName, loadIcons(collectionName));
14
29
  }
15
- fillRegistry(bundleData);
16
- resolveFn();
30
+
31
+ return iconCollectionPromises.get(collectionName);
17
32
  };
18
33
 
19
- const fillRegistry = bundleData => {
34
+ const _fillRegistry = bundleData => {
20
35
  Object.keys(bundleData.data).forEach(iconName => {
21
36
  const iconData = bundleData.data[iconName];
22
37
 
@@ -25,8 +40,96 @@ const fillRegistry = bundleData => {
25
40
  ltr: iconData.ltr,
26
41
  accData: iconData.acc,
27
42
  collection: bundleData.collection,
43
+ packageName: bundleData.packageName,
28
44
  });
29
45
  });
30
46
  };
31
47
 
32
- export { registerIconBundle }; // eslint-disable-line
48
+ // set
49
+ const registerIcon = (name, { pathData, ltr, accData, collection, packageName } = {}) => { // eslint-disable-line
50
+ if (!collection) {
51
+ collection = getEffectiveDefaultIconCollection();
52
+ }
53
+
54
+ const key = `${collection}/${name}`;
55
+ registry.set(key, {
56
+ pathData,
57
+ ltr,
58
+ accData,
59
+ packageName,
60
+ });
61
+ };
62
+
63
+ const _parseName = name => {
64
+ // silently support ui5-compatible URIs
65
+ if (name.startsWith("sap-icon://")) {
66
+ name = name.replace("sap-icon://", "");
67
+ }
68
+
69
+ let collection;
70
+ [name, collection] = name.split("/").reverse();
71
+ collection = collection || getEffectiveDefaultIconCollection();
72
+
73
+ // Normalize collection name.
74
+ // - resolve `SAP-icons-TNT` to `tnt`.
75
+ // - resolve `BusinessSuiteInAppSymbols` to `business-suite`.
76
+ // - resolve `horizon` to `SAP-icons-v5`,
77
+ // Note: aliases can be made as a feature, if more collections need it or more aliases are needed.
78
+ collection = _normalizeCollection(collection);
79
+ name = name.replace("icon-", "");
80
+
81
+ const registryKey = `${collection}/${name}`;
82
+ return { name, collection, registryKey };
83
+ };
84
+
85
+ const getIconDataSync = nameProp => {
86
+ const { registryKey } = _parseName(nameProp);
87
+ return registry.get(registryKey);
88
+ };
89
+
90
+ const getIconData = async nameProp => {
91
+ const { collection, registryKey } = _parseName(nameProp);
92
+
93
+ let iconData = ICON_NOT_FOUND;
94
+ try {
95
+ iconData = await _loadIconCollectionOnce(collection);
96
+ } catch (e) {
97
+ console.error(e.message); /* eslint-disable-line */
98
+ }
99
+
100
+ if (iconData === ICON_NOT_FOUND) {
101
+ return iconData;
102
+ }
103
+
104
+ if (!registry.has(registryKey)) {
105
+ // not filled by another await. many getters will await on the same loader, but fill only once
106
+ _fillRegistry(iconData);
107
+ }
108
+ return registry.get(registryKey);
109
+ };
110
+
111
+ // test page usage only
112
+ const _getRegisteredNames = async () => {
113
+ // fetch one icon of each collection to trigger the bundle load
114
+ await getIconData("edit");
115
+ await getIconData("tnt/arrow");
116
+ await getIconData("business-suite/3d");
117
+ return Array.from(registry.keys());
118
+ };
119
+
120
+ const _normalizeCollection = collectionName => {
121
+ if (IconCollectionsAlias[collectionName]) {
122
+ return IconCollectionsAlias[collectionName];
123
+ }
124
+
125
+ return collectionName;
126
+ };
127
+
128
+ export {
129
+ registerIconBundle,
130
+ registerIconLoader,
131
+ getIconData,
132
+ getIconDataSync,
133
+ registerIcon,
134
+ _getRegisteredNames,
135
+ };
@@ -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
+ };
@@ -1,23 +1,34 @@
1
- import { fetchJsonOnce } from "../util/FetchHelper.js";
2
1
  import { attachLanguageChange } from "../locale/languageChange.js";
3
2
  import getLocale from "../locale/getLocale.js";
4
- import { getFeature } from "../FeaturesRegistry.js";
5
3
  import { DEFAULT_LOCALE, SUPPORTED_LOCALES } from "../generated/AssetParameters.js";
6
- import { getEffectiveAssetPath } from "../util/EffectiveAssetPath.js";
7
-
8
- const resources = new Map();
9
- const cldrData = {};
10
- const cldrUrls = {};
4
+ import { getFeature } from "../FeaturesRegistry.js";
11
5
 
12
- // externally configurable mapping function for resolving (localeId -> URL)
13
- // default implementation - ui5 CDN
14
- let cldrMappingFn = locale => `https://ui5.sap.com/1.60.2/resources/sap/ui/core/cldr/${locale}.json`;
6
+ const localeDataMap = new Map();
7
+ const loaders = new Map();
8
+ const cldrPromises = new Map();
9
+ const reportedErrors = new Set();
10
+ let warningShown = false;
15
11
 
16
12
  const M_ISO639_OLD_TO_NEW = {
17
13
  "iw": "he",
18
14
  "ji": "yi",
19
15
  "in": "id",
20
- "sh": "sr",
16
+ };
17
+
18
+ const DEV_MODE = false;
19
+
20
+ const _showAssetsWarningOnce = localeId => {
21
+ if (warningShown) {
22
+ return;
23
+ }
24
+
25
+ if (!DEV_MODE) {
26
+ console.warn(`[LocaleData] Supported locale "${localeId}" not configured, import the "Assets.js" module from the webcomponents package you are using.`); /* eslint-disable-line */
27
+ } else {
28
+ console.warn(`[LocaleData] Note: in dev mode, CLDR assets might be disabled for performance reasons. Try running "ENABLE_CLDR=1 yarn start" to test CLDR assets.`); /* eslint-disable-line */
29
+ }
30
+
31
+ warningShown = true;
21
32
  };
22
33
 
23
34
  const calcLocale = (language, region, script) => {
@@ -36,87 +47,108 @@ const calcLocale = (language, region, script) => {
36
47
  }
37
48
  }
38
49
 
50
+ // Special case 3: for Serbian, there are cyrillic and latin scripts, "sh" and "sr-latn" map to "latin", "sr" maps to cyrillic.
51
+ if (language === "sh" || (language === "sr" && script === "Latn")) {
52
+ language = "sr";
53
+ region = "Latn";
54
+ }
55
+
39
56
  // try language + region
40
57
  let localeId = `${language}_${region}`;
41
- if (!SUPPORTED_LOCALES.includes(localeId)) {
42
- // fallback to language only
43
- localeId = language;
58
+ if (SUPPORTED_LOCALES.includes(localeId)) {
59
+ if (loaders.has(localeId)) {
60
+ // supported and has loader
61
+ return localeId;
62
+ }
63
+
64
+ // supported, no loader - fallback to default and warn
65
+ _showAssetsWarningOnce(localeId);
66
+ return DEFAULT_LOCALE;
44
67
  }
45
- if (!SUPPORTED_LOCALES.includes(localeId)) {
46
- // fallback to english
47
- localeId = DEFAULT_LOCALE;
68
+
69
+ // not supported, try language only
70
+ localeId = language;
71
+ if (SUPPORTED_LOCALES.includes(localeId)) {
72
+ if (loaders.has(localeId)) {
73
+ // supported and has loader
74
+ return localeId;
75
+ }
76
+
77
+ // supported, no loader - fallback to default and warn
78
+ _showAssetsWarningOnce(localeId);
79
+ return DEFAULT_LOCALE;
48
80
  }
49
81
 
50
- return localeId;
82
+ // not supported - fallback to default locale
83
+ return DEFAULT_LOCALE;
51
84
  };
52
85
 
86
+ // internal set data
87
+ const setLocaleData = (localeId, content) => {
88
+ localeDataMap.set(localeId, content);
89
+ };
53
90
 
54
- const resolveMissingMappings = () => {
55
- if (!cldrMappingFn) {
56
- return;
91
+ // external getSync
92
+ const getLocaleData = localeId => {
93
+ // if there is no loader, the default fallback was fetched and a warning was given - use default locale instead
94
+ if (!loaders.has(localeId)) {
95
+ localeId = DEFAULT_LOCALE;
57
96
  }
58
97
 
59
- const missingLocales = SUPPORTED_LOCALES.filter(locale => !cldrData[locale] && !cldrUrls[locale]);
60
- missingLocales.forEach(locale => {
61
- cldrUrls[locale] = cldrMappingFn(locale);
62
- });
63
- };
98
+ const content = localeDataMap.get(localeId);
99
+ if (!content) {
100
+ throw new Error(`CLDR data for locale ${localeId} is not loaded!`);
101
+ }
64
102
 
65
- const registerModuleContent = (moduleName, content) => {
66
- resources.set(moduleName, content);
103
+ return content;
67
104
  };
68
105
 
69
- const getModuleContent = moduleName => {
70
- const moduleContent = resources.get(moduleName);
71
- if (moduleContent) {
72
- return moduleContent;
73
- }
106
+ // load bundle over the network once
107
+ const _loadCldrOnce = localeId => {
108
+ const loadCldr = loaders.get(localeId);
74
109
 
75
- const missingModule = moduleName.match(/sap\/ui\/core\/cldr\/(\w+)\.json/);
76
- if (missingModule) {
77
- throw new Error(`CLDR data for locale ${missingModule[1]} is not loaded!`);
110
+ if (!cldrPromises.get(localeId)) {
111
+ cldrPromises.set(localeId, loadCldr(localeId));
78
112
  }
79
113
 
80
- throw new Error(`Unknown module ${moduleName}`);
114
+ return cldrPromises.get(localeId);
81
115
  };
82
116
 
117
+ // external getAsync
83
118
  const fetchCldr = async (language, region, script) => {
84
- resolveMissingMappings();
85
119
  const localeId = calcLocale(language, region, script);
86
120
 
87
- let cldrObj = cldrData[localeId];
88
- const url = cldrUrls[localeId];
89
-
121
+ // reuse OpenUI5 CLDR if present
90
122
  const OpenUI5Support = getFeature("OpenUI5Support");
91
- if (!cldrObj && OpenUI5Support) {
92
- cldrObj = OpenUI5Support.getLocaleDataObject();
123
+ if (OpenUI5Support) {
124
+ const cldrContent = OpenUI5Support.getLocaleDataObject();
125
+ if (cldrContent) {
126
+ // only if openui5 actually returned valid content
127
+ setLocaleData(localeId, cldrContent);
128
+ return;
129
+ }
93
130
  }
94
131
 
95
- if (cldrObj) {
96
- // inlined from build or fetched independently
97
- registerModuleContent(`sap/ui/core/cldr/${localeId}.json`, cldrObj);
98
- } else if (url) {
99
- // fetch it
100
- const cldrContent = await fetchJsonOnce(getEffectiveAssetPath(url));
101
- registerModuleContent(`sap/ui/core/cldr/${localeId}.json`, cldrContent);
132
+ // fetch it
133
+ try {
134
+ const cldrContent = await _loadCldrOnce(localeId);
135
+ setLocaleData(localeId, cldrContent);
136
+ } catch (e) {
137
+ if (!reportedErrors.has(e.message)) {
138
+ reportedErrors.add(e.message);
139
+ console.error(e.message); /* eslint-disable-line */
140
+ }
102
141
  }
103
142
  };
104
143
 
105
- const registerCldr = (locale, url) => {
106
- cldrUrls[locale] = url;
107
- };
108
-
109
- const setCldrData = (locale, data) => {
110
- cldrData[locale] = data;
144
+ const registerLocaleDataLoader = (localeId, loader) => {
145
+ loaders.set(localeId, loader);
111
146
  };
112
147
 
113
- const getCldrData = locale => {
114
- return cldrData[locale];
115
- };
116
-
117
- const _registerMappingFunction = mappingFn => {
118
- cldrMappingFn = mappingFn;
119
- };
148
+ // register default loader for "en" from ui5 CDN (dev workflow without assets)
149
+ registerLocaleDataLoader("en", async runtimeLocaleId => {
150
+ return (await fetch(`https://ui5.sap.com/1.60.2/resources/sap/ui/core/cldr/en.json`)).json();
151
+ });
120
152
 
121
153
  // When the language changes dynamically (the user calls setLanguage),
122
154
  // re-fetch the required CDRD data.
@@ -126,10 +158,7 @@ attachLanguageChange(() => {
126
158
  });
127
159
 
128
160
  export {
161
+ registerLocaleDataLoader,
129
162
  fetchCldr,
130
- registerCldr,
131
- setCldrData,
132
- getCldrData,
133
- getModuleContent,
134
- _registerMappingFunction,
163
+ getLocaleData,
135
164
  };
@@ -1,10 +1,7 @@
1
- import { fetchJsonOnce, fetchTextOnce } from "../util/FetchHelper.js";
2
1
  import { DEFAULT_THEME } from "../generated/AssetParameters.js";
3
- import getFileExtension from "../util/getFileExtension.js";
4
- import { getEffectiveAssetPath } from "../util/EffectiveAssetPath.js";
5
2
 
6
- const themeURLs = new Map();
7
3
  const themeStyles = new Map();
4
+ const loaders = new Map();
8
5
  const registeredPackages = new Set();
9
6
  const registeredThemes = new Set();
10
7
 
@@ -16,29 +13,19 @@ const registeredThemes = new Set();
16
13
  * Example usage:
17
14
  * 1) Pass the CSS Vars as a string directly.
18
15
  * registerThemeProperties("my-package", "my_theme", ":root{--var1: red;}");
19
- * 2) Pass the CSS Vars as an object directly
20
- * registerThemeProperties("my-package", "my_theme", {"_": ":root{--var1: red;}"});
21
- * 3) Pass a URL to a CSS file, containing the CSS Vars. Will be fetched on demand, not upon registration.
22
- * registerThemeProperties("my-package", "my_theme", "http://url/to/my/theme.css");
23
- * 4) Pass a URL to a JSON file, containing the CSS Vars in its "_" property. Will be fetched on demand, not upon registration.
24
- * registerThemeProperties("my-package", "my_theme", "http://url/to/my/theme.json");
25
16
  *
26
17
  * @public
27
18
  * @param packageName - the NPM package for which CSS Vars are registered
28
19
  * @param themeName - the theme which the CSS Vars implement
29
- * @param style - can be one of four options: a string, an object with a "_" property, URL to a CSS file, or URL to a JSON file with a "_" property
20
+ * @param style - the style content directly
21
+ * @deprecated
30
22
  */
31
- const registerThemeProperties = (packageName, themeName, style) => {
32
- if (style._) {
33
- // JSON object like ({"_": ":root"})
34
- themeStyles.set(`${packageName}_${themeName}`, style._);
35
- } else if (style.includes(":root") || style === "") {
36
- // pure string, including empty string
37
- themeStyles.set(`${packageName}_${themeName}`, style);
38
- } else {
39
- // url for fetching
40
- themeURLs.set(`${packageName}_${themeName}`, style);
41
- }
23
+ const registerThemeProperties = (_packageName, _themeName, _style) => {
24
+ throw new Error("`registerThemeProperties` has been depracated. Use `registerThemePropertiesLoader` instead.");
25
+ };
26
+
27
+ const registerThemePropertiesLoader = (packageName, themeName, loader) => {
28
+ loaders.set(`${packageName}/${themeName}`, loader);
42
29
  registeredPackages.add(packageName);
43
30
  registeredThemes.add(themeName);
44
31
  };
@@ -55,23 +42,25 @@ const getThemeProperties = async (packageName, themeName) => {
55
42
  return themeStyles.get(`${packageName}_${DEFAULT_THEME}`);
56
43
  }
57
44
 
58
- const data = await fetchThemeProperties(packageName, themeName);
45
+ const loader = loaders.get(`${packageName}/${themeName}`);
46
+ if (!loader) {
47
+ // no themes for package
48
+ console.error(`Theme [${themeName}] not registered for package [${packageName}]`); /* eslint-disable-line */
49
+ return;
50
+ }
51
+ let data;
52
+ try {
53
+ data = await loader(themeName);
54
+ } catch (e) {
55
+ console.error(packageName, e.message); /* eslint-disable-line */
56
+ return;
57
+ }
59
58
  const themeProps = data._ || data;
60
59
 
61
60
  themeStyles.set(`${packageName}_${themeName}`, themeProps);
62
61
  return themeProps;
63
62
  };
64
63
 
65
- const fetchThemeProperties = async (packageName, themeName) => {
66
- const url = themeURLs.get(`${packageName}_${themeName}`);
67
-
68
- if (!url) {
69
- throw new Error(`You have to import the ${packageName}/dist/Assets.js module to switch to additional themes`);
70
- }
71
-
72
- return getFileExtension(url) === ".css" ? fetchTextOnce(url) : fetchJsonOnce(getEffectiveAssetPath(url));
73
- };
74
-
75
64
  const getRegisteredPackages = () => {
76
65
  return registeredPackages;
77
66
  };
@@ -81,6 +70,7 @@ const isThemeRegistered = theme => {
81
70
  };
82
71
 
83
72
  export {
73
+ registerThemePropertiesLoader,
84
74
  registerThemeProperties,
85
75
  getThemeProperties,
86
76
  getRegisteredPackages,
@@ -1,23 +1,31 @@
1
- import { getFeature } from "../FeaturesRegistry.js";
2
1
  import getLocale from "../locale/getLocale.js";
3
2
  import { attachLanguageChange } from "../locale/languageChange.js";
4
- import { fetchTextOnce } from "../util/FetchHelper.js";
5
3
  import normalizeLocale from "../locale/normalizeLocale.js";
6
4
  import nextFallbackLocale from "../locale/nextFallbackLocale.js";
7
5
  import { DEFAULT_LANGUAGE } from "../generated/AssetParameters.js";
8
- import { getEffectiveAssetPath } from "../util/EffectiveAssetPath.js";
9
- import { getUseDefaultLanguage } from "../config/Language.js";
6
+ import { getFetchDefaultLanguage } from "../config/Language.js";
7
+
8
+ // contains package names for which the warning has been shown
9
+ const warningShown = new Set();
10
+ const reportedErrors = new Set();
10
11
 
11
12
  const bundleData = new Map();
12
- const bundleURLs = new Map();
13
+ const bundlePromises = new Map();
14
+ const loaders = new Map();
13
15
 
14
16
  /**
15
- * Sets a map with texts and ID the are related to.
16
- * @param {string} packageName package ID that the i18n bundle will be related to
17
- * @param {Object} data an object with string locales as keys and text translataions as values
18
- * @public
17
+ *
18
+ * @param {string} packageName for which package this loader can fetch data
19
+ * @param {function} loader async function that will be passed a localeId and should return a JSON object
20
+ * @param {Array} localeIds Array of locale IDs that this loader can handle
19
21
  */
20
- const setI18nBundleData = (packageName, data) => {
22
+ const registerI18nLoader = (packageName, localeId, loader) => {
23
+ // register loader by key
24
+ const bundleKey = `${packageName}/${localeId}`;
25
+ loaders.set(bundleKey, loader);
26
+ };
27
+
28
+ const _setI18nBundleData = (packageName, data) => {
21
29
  bundleData.set(packageName, data);
22
30
  };
23
31
 
@@ -26,18 +34,36 @@ const getI18nBundleData = packageName => {
26
34
  };
27
35
 
28
36
  /**
29
- * Registers a map of locale/url information, to be used by the <code>fetchI18nBundle</code> method.
30
- * Note: In order to be able to register ".properties" files, you must import the following module:
31
- * import "@ui5/webcomponents-base/dist/features/PropertiesFormatSupport.js";
32
- *
33
- * @param {string} packageName package ID that the i18n bundle will be related to
34
- * @param {Object} bundle an object with string locales as keys and the URLs (in .json or .properties format - see the note above) where the corresponding locale can be fetched from, f.e {"en": "path/en.json", ...}
35
- *
36
37
  * @public
38
+ * @deprecated
37
39
  */
38
- const registerI18nBundle = (packageName, bundle) => {
39
- const oldBundle = bundleURLs.get(packageName) || {};
40
- bundleURLs.set(packageName, Object.assign({}, oldBundle, bundle));
40
+ const registerI18nBundle = (_packageName, _bundle) => {
41
+ throw new Error("This method has been removed. Use `registerI18nLoader` instead.");
42
+ };
43
+
44
+ const _hasLoader = (packageName, localeId) => {
45
+ const bundleKey = `${packageName}/${localeId}`;
46
+ return loaders.has(bundleKey);
47
+ };
48
+
49
+ // load bundle over the network once
50
+ const _loadMessageBundleOnce = (packageName, localeId) => {
51
+ const bundleKey = `${packageName}/${localeId}`;
52
+ const loadMessageBundle = loaders.get(bundleKey);
53
+
54
+ if (!bundlePromises.get(bundleKey)) {
55
+ bundlePromises.set(bundleKey, loadMessageBundle(localeId));
56
+ }
57
+
58
+ return bundlePromises.get(bundleKey);
59
+ };
60
+
61
+ const _showAssetsWarningOnce = packageName => {
62
+ if (!warningShown.has(packageName)) {
63
+ console.warn(`[${packageName}]: Message bundle assets are not configured. Falling back to English texts.`, /* eslint-disable-line */
64
+ ` Add \`import "${packageName}/dist/Assets.js"\` in your bundle and make sure your build tool supports dynamic imports and JSON imports. See section "Assets" in the documentation for more information.`); /* eslint-disable-line */
65
+ warningShown.add(packageName);
66
+ }
41
67
  };
42
68
 
43
69
  /**
@@ -50,50 +76,35 @@ const registerI18nBundle = (packageName, bundle) => {
50
76
  * @public
51
77
  */
52
78
  const fetchI18nBundle = async packageName => {
53
- const bundlesForPackage = bundleURLs.get(packageName);
54
-
55
- if (!bundlesForPackage) {
56
- console.warn(`Message bundle assets are not configured. Falling back to English texts.`, /* eslint-disable-line */
57
- ` You need to import ${packageName}/dist/Assets.js with a build tool that supports JSON imports.`); /* eslint-disable-line */
58
- return;
59
- }
60
-
61
79
  const language = getLocale().getLanguage();
62
80
  const region = getLocale().getRegion();
63
- const useDefaultLanguage = getUseDefaultLanguage();
64
81
  let localeId = normalizeLocale(language + (region ? `-${region}` : ``));
65
82
 
66
- while (localeId !== DEFAULT_LANGUAGE && !bundlesForPackage[localeId]) {
83
+ while (localeId !== DEFAULT_LANGUAGE && !_hasLoader(packageName, localeId)) {
67
84
  localeId = nextFallbackLocale(localeId);
68
85
  }
69
86
 
70
- if (useDefaultLanguage && localeId === DEFAULT_LANGUAGE) {
71
- setI18nBundleData(packageName, null); // reset for the default language (if data was set for a previous language)
87
+ // use default language unless configured to always fetch it from the network
88
+ const fetchDefaultLanguage = getFetchDefaultLanguage();
89
+ if (localeId === DEFAULT_LANGUAGE && !fetchDefaultLanguage) {
90
+ _setI18nBundleData(packageName, null); // reset for the default language (if data was set for a previous language)
72
91
  return;
73
92
  }
74
93
 
75
- const bundleURL = bundlesForPackage[localeId];
76
-
77
- if (typeof bundleURL === "object") { // inlined from build
78
- setI18nBundleData(packageName, bundleURL);
94
+ if (!_hasLoader(packageName, localeId)) {
95
+ _showAssetsWarningOnce(packageName);
79
96
  return;
80
97
  }
81
98
 
82
- const content = await fetchTextOnce(getEffectiveAssetPath(bundleURL));
83
- let parser;
84
- if (content.startsWith("{")) {
85
- parser = JSON.parse;
86
- } else {
87
- const PropertiesFormatSupport = getFeature("PropertiesFormatSupport");
88
- if (!PropertiesFormatSupport) {
89
- throw new Error(`In order to support .properties files, please: import "@ui5/webcomponents-base/dist/features/PropertiesFormatSupport.js";`);
99
+ try {
100
+ const data = await _loadMessageBundleOnce(packageName, localeId);
101
+ _setI18nBundleData(packageName, data);
102
+ } catch (e) {
103
+ if (!reportedErrors.has(e.message)) {
104
+ reportedErrors.add(e.message);
105
+ console.error(e.message); /* eslint-disable-line */
90
106
  }
91
- parser = PropertiesFormatSupport.parser;
92
107
  }
93
-
94
- const data = parser(content);
95
-
96
- setI18nBundleData(packageName, data);
97
108
  };
98
109
 
99
110
  // When the language changes dynamically (the user calls setLanguage), re-fetch all previously fetched bundles
@@ -103,8 +114,8 @@ attachLanguageChange(() => {
103
114
  });
104
115
 
105
116
  export {
117
+ registerI18nLoader,
106
118
  fetchI18nBundle,
107
119
  registerI18nBundle,
108
- setI18nBundleData,
109
120
  getI18nBundleData,
110
121
  };
@@ -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;