@ui5/webcomponents-base 0.33.0 → 1.0.0

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 (115) hide show
  1. package/.eslintignore +2 -1
  2. package/CHANGELOG.md +34 -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 +5 -0
  7. package/dist/EventProvider.js +19 -25
  8. package/dist/FontFace.js +7 -95
  9. package/dist/InitialConfiguration.js +11 -7
  10. package/dist/Keys.js +9 -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 +43 -59
  16. package/dist/UI5ElementMetadata.js +9 -1
  17. package/dist/asset-registries/Icons.js +26 -8
  18. package/dist/asset-registries/Illustrations.js +10 -3
  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/generated/AssetParameters.js +1 -1
  27. package/dist/generated/css/FontFace.css.js +5 -0
  28. package/dist/generated/css/OverrideFontFace.css.js +5 -0
  29. package/dist/generated/css/SystemCSSVars.css.js +5 -0
  30. package/dist/i18nBundle.js +33 -2
  31. package/dist/renderer/LitRenderer.js +7 -4
  32. package/dist/renderer/directives/style-map.js +72 -0
  33. package/dist/resources/bundle.esm.js +19 -8
  34. package/dist/resources/bundle.esm.js.map +1 -1
  35. package/dist/sap/base/Log.js +2 -10
  36. package/dist/sap/base/assert.js +1 -5
  37. package/dist/test-resources/elements/WithStaticArea.js +2 -1
  38. package/dist/test-resources/pages/AllTestElements.html +3 -0
  39. package/dist/test-resources/pages/i18n.html +1 -3
  40. package/dist/test-resources/specs/ConfigurationChange.spec.js +9 -9
  41. package/dist/test-resources/specs/ConfigurationScript.spec.js +24 -24
  42. package/dist/test-resources/specs/ConfigurationURL.spec.js +33 -33
  43. package/dist/test-resources/specs/CustomTheme.spec.js +7 -7
  44. package/dist/test-resources/specs/EventProvider.spec.js +63 -0
  45. package/dist/test-resources/specs/StaticArea.spec.js +55 -13
  46. package/dist/test-resources/specs/Theming.spec.js +11 -11
  47. package/dist/test-resources/specs/UI5ElementInvalidation.js +29 -29
  48. package/dist/test-resources/specs/UI5ElementLifecycle.js +11 -11
  49. package/dist/test-resources/specs/UI5ElementListenForChildPropChanges.spec.js +11 -11
  50. package/dist/test-resources/specs/UI5ElementMetadataExt.js +8 -8
  51. package/dist/test-resources/specs/UI5ElementPropertyValidation.js +6 -6
  52. package/dist/test-resources/specs/UI5ElementPropsAndAttrs.spec.js +36 -36
  53. package/dist/test-resources/specs/UI5ElementShadowDOM.js +9 -9
  54. package/dist/test-resources/specs/UI5ElementSlots.js +9 -9
  55. package/dist/theming/CustomStyle.js +23 -3
  56. package/dist/theming/applyTheme.js +5 -8
  57. package/dist/theming/getEffectiveLinksHrefs.js +20 -0
  58. package/dist/theming/getStylesString.js +4 -2
  59. package/dist/theming/getThemeDesignerTheme.js +2 -1
  60. package/dist/theming/preloadLinks.js +23 -0
  61. package/dist/types/DataType.js +12 -0
  62. package/dist/types/Float.js +4 -0
  63. package/dist/types/Integer.js +4 -0
  64. package/dist/updateShadowRoot.js +8 -4
  65. package/dist/util/createLinkInHead.js +19 -0
  66. package/dist/util/encodeXML.js +35 -0
  67. package/dist/util/escapeRegex.js +10 -0
  68. package/dist/util/generateHighlightedMarkup.js +42 -0
  69. package/hash.txt +1 -1
  70. package/lib/generate-asset-parameters/index.js +0 -1
  71. package/lib/generate-styles/index.js +18 -0
  72. package/package-scripts.js +9 -6
  73. package/package.json +10 -12
  74. package/src/CSP.js +59 -0
  75. package/src/Device.js +5 -0
  76. package/src/EventProvider.js +19 -25
  77. package/src/FontFace.js +7 -95
  78. package/src/InitialConfiguration.js +11 -7
  79. package/src/Keys.js +9 -0
  80. package/src/ManagedStyles.js +83 -0
  81. package/src/Render.js +3 -1
  82. package/src/StaticAreaItem.js +11 -9
  83. package/src/SystemCSSVars.js +4 -25
  84. package/src/UI5Element.js +43 -59
  85. package/src/UI5ElementMetadata.js +9 -1
  86. package/src/asset-registries/Icons.js +26 -8
  87. package/src/asset-registries/Illustrations.js +10 -3
  88. package/src/asset-registries/LocaleData.js +11 -2
  89. package/src/assets-meta/IconCollectionsAlias.js +18 -0
  90. package/src/config/Theme.js +14 -0
  91. package/src/css/FontFace.css +45 -0
  92. package/src/css/OverrideFontFace.css +32 -0
  93. package/src/css/SystemCSSVars.css +17 -0
  94. package/src/delegate/ItemNavigation.js +66 -0
  95. package/src/i18nBundle.js +33 -2
  96. package/src/renderer/LitRenderer.js +7 -4
  97. package/src/renderer/directives/style-map.js +72 -0
  98. package/src/theming/CustomStyle.js +23 -3
  99. package/src/theming/applyTheme.js +5 -8
  100. package/src/theming/getEffectiveLinksHrefs.js +20 -0
  101. package/src/theming/getStylesString.js +4 -2
  102. package/src/theming/getThemeDesignerTheme.js +2 -1
  103. package/src/theming/preloadLinks.js +23 -0
  104. package/src/types/DataType.js +12 -0
  105. package/src/types/Float.js +4 -0
  106. package/src/types/Integer.js +4 -0
  107. package/src/updateShadowRoot.js +8 -4
  108. package/src/util/createLinkInHead.js +19 -0
  109. package/src/util/encodeXML.js +35 -0
  110. package/src/util/escapeRegex.js +10 -0
  111. package/src/util/generateHighlightedMarkup.js +42 -0
  112. package/dist/config/AssetsPath.js +0 -17
  113. package/dist/theming/createThemePropertiesStyleTag.js +0 -20
  114. package/src/config/AssetsPath.js +0 -17
  115. package/src/theming/createThemePropertiesStyleTag.js +0 -20
@@ -1,9 +1,11 @@
1
1
  const getStylesString = styles => {
2
2
  if (Array.isArray(styles)) {
3
- return flatten(styles.filter(style => !!style)).join(" ");
3
+ return flatten(styles.filter(style => !!style)).map(style => {
4
+ return typeof style === "string" ? style : style.content;
5
+ }).join(" ");
4
6
  }
5
7
 
6
- return styles;
8
+ return typeof styles === "string" ? styles : styles.content;
7
9
  };
8
10
 
9
11
  const flatten = arr => {
@@ -1,6 +1,6 @@
1
1
  const getThemeMetadata = () => {
2
2
  // Check if the class was already applied, most commonly to the link/style tag with the CSS Variables
3
- let el = document.querySelector(".sapThemeMetaData-Base-baseLib");
3
+ let el = document.querySelector(".sapThemeMetaData-Base-baseLib") || document.querySelector(".sapThemeMetaData-UI5-sap-ui-core");
4
4
  if (el) {
5
5
  return getComputedStyle(el).backgroundImage;
6
6
  }
@@ -8,6 +8,7 @@ const getThemeMetadata = () => {
8
8
  el = document.createElement("span");
9
9
  el.style.display = "none";
10
10
  el.classList.add("sapThemeMetaData-Base-baseLib");
11
+ el.classList.add("sapThemeMetaData-UI5-sap-ui-core");
11
12
  document.body.appendChild(el);
12
13
  const metadata = getComputedStyle(el).backgroundImage;
13
14
  document.body.removeChild(el);
@@ -0,0 +1,23 @@
1
+ import getEffectiveLinksHrefs from "./getEffectiveLinksHrefs.js";
2
+ import createLinkInHead from "../util/createLinkInHead.js";
3
+ import { shouldUseLinks, shouldPreloadLinks } from "../CSP.js";
4
+
5
+ const preloaded = new Set();
6
+
7
+ const preloadLinks = ElementClass => {
8
+ if (!shouldUseLinks() || !shouldPreloadLinks()) {
9
+ return;
10
+ }
11
+
12
+ const linksHrefs = getEffectiveLinksHrefs(ElementClass, false) || [];
13
+ const staticAreaLinksHrefs = getEffectiveLinksHrefs(ElementClass, true) || [];
14
+
15
+ [...linksHrefs, ...staticAreaLinksHrefs].forEach(href => {
16
+ if (!preloaded.has(href)) {
17
+ createLinkInHead(href, { rel: "preload", as: "style" });
18
+ preloaded.add(href);
19
+ }
20
+ });
21
+ };
22
+
23
+ export default preloadLinks;
@@ -11,6 +11,18 @@ class DataType {
11
11
  static isValid(value) {
12
12
  }
13
13
 
14
+ static attributeToProperty(attributeValue) {
15
+ return attributeValue;
16
+ }
17
+
18
+ static propertyToAttribute(propertyValue) {
19
+ return `${propertyValue}`;
20
+ }
21
+
22
+ static valuesAreEqual(value1, value2) {
23
+ return value1 === value2;
24
+ }
25
+
14
26
  static generateTypeAccessors(types) {
15
27
  Object.keys(types).forEach(type => {
16
28
  Object.defineProperty(this, type, {
@@ -5,6 +5,10 @@ class Float extends DataType {
5
5
  // Assuming that integers are floats as well!
6
6
  return Number(value) === value;
7
7
  }
8
+
9
+ static attributeToProperty(attributeValue) {
10
+ return parseFloat(attributeValue);
11
+ }
8
12
  }
9
13
 
10
14
  export default Float;
@@ -4,6 +4,10 @@ class Integer extends DataType {
4
4
  static isValid(value) {
5
5
  return Number.isInteger(value);
6
6
  }
7
+
8
+ static attributeToProperty(attributeValue) {
9
+ return parseInt(attributeValue);
10
+ }
7
11
  }
8
12
 
9
13
  export default Integer;
@@ -1,7 +1,9 @@
1
1
  import executeTemplate from "./renderer/executeTemplate.js";
2
2
  import getConstructableStyle from "./theming/getConstructableStyle.js";
3
3
  import getEffectiveStyle from "./theming/getEffectiveStyle.js";
4
+ import getEffectiveLinksHrefs from "./theming/getEffectiveLinksHrefs.js";
4
5
  import isLegacyBrowser from "./isLegacyBrowser.js";
6
+ import { shouldUseLinks } from "./CSP.js";
5
7
 
6
8
  /**
7
9
  * Updates the shadow root of a UI5Element or its static area item
@@ -9,18 +11,20 @@ import isLegacyBrowser from "./isLegacyBrowser.js";
9
11
  * @param forStaticArea
10
12
  */
11
13
  const updateShadowRoot = (element, forStaticArea = false) => {
12
- let styleToPrepend;
14
+ let styleStrOrHrefsArr;
13
15
  const template = forStaticArea ? "staticAreaTemplate" : "template";
14
16
  const shadowRoot = forStaticArea ? element.staticAreaItem.shadowRoot : element.shadowRoot;
15
17
  const renderResult = executeTemplate(element.constructor[template], element);
16
18
 
17
- if (document.adoptedStyleSheets) { // Chrome
19
+ if (shouldUseLinks()) {
20
+ styleStrOrHrefsArr = getEffectiveLinksHrefs(element.constructor, forStaticArea);
21
+ } else if (document.adoptedStyleSheets) { // Chrome
18
22
  shadowRoot.adoptedStyleSheets = getConstructableStyle(element.constructor, forStaticArea);
19
23
  } else if (!isLegacyBrowser()) { // FF, Safari
20
- styleToPrepend = getEffectiveStyle(element.constructor, forStaticArea);
24
+ styleStrOrHrefsArr = getEffectiveStyle(element.constructor, forStaticArea);
21
25
  }
22
26
 
23
- element.constructor.render(renderResult, shadowRoot, styleToPrepend, { host: element });
27
+ element.constructor.render(renderResult, shadowRoot, styleStrOrHrefsArr, { host: element });
24
28
  };
25
29
 
26
30
  export default updateShadowRoot;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Creates a <link> tag in the <head> tag
3
+ * @param href - the CSS
4
+ * @param attributes - optional attributes to add to the tag
5
+ * @returns {HTMLElement}
6
+ */
7
+ const createLinkInHead = (href, attributes = {}) => {
8
+ const link = document.createElement("link");
9
+ link.type = "text/css";
10
+ link.rel = "stylesheet";
11
+
12
+ Object.entries(attributes).forEach(pair => link.setAttribute(...pair));
13
+
14
+ link.href = href;
15
+ document.head.appendChild(link);
16
+ return link;
17
+ };
18
+
19
+ export default createLinkInHead;
@@ -0,0 +1,35 @@
1
+ const fnToHex = (iChar, iLength) => {
2
+ let sHex = iChar.toString(16);
3
+ if (iLength) {
4
+ sHex = sHex.padStart(iLength, "0");
5
+ }
6
+ return sHex;
7
+ };
8
+
9
+ const rHtml = /[\x00-\x2b\x2f\x3a-\x40\x5b-\x5e\x60\x7b-\xff\u2028\u2029]/g, // eslint-disable-line no-control-regex
10
+ rHtmlReplace = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]/, // eslint-disable-line no-control-regex
11
+ mHtmlLookup = {
12
+ "<": "&lt;",
13
+ ">": "&gt;",
14
+ "&": "&amp;",
15
+ "\"": "&quot;",
16
+ };
17
+
18
+ const fnHtml = sChar => {
19
+ let sEncoded = mHtmlLookup[sChar];
20
+ if (!sEncoded) {
21
+ if (rHtmlReplace.test(sChar)) {
22
+ sEncoded = "&#xfffd;";
23
+ } else {
24
+ sEncoded = `&#x${fnToHex(sChar.charCodeAt(0))};`;
25
+ }
26
+ mHtmlLookup[sChar] = sEncoded;
27
+ }
28
+ return sEncoded;
29
+ };
30
+
31
+ const fnEncodeXML = sString => {
32
+ return sString.replace(rHtml, fnHtml);
33
+ };
34
+
35
+ export default fnEncodeXML;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Escape a regular expression text so that it can be used in a regular expression.
3
+ * @param {string} text The string to be interpreted literally
4
+ * @returns Regular expression string to pass to regex
5
+ */
6
+ function escapeRegex(text) {
7
+ return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8
+ }
9
+
10
+ export default escapeRegex;
@@ -0,0 +1,42 @@
1
+ import escapeRegex from "./escapeRegex.js";
2
+ import encodeXML from "./encodeXML.js";
3
+
4
+ // utility to replace all occurances of a string
5
+ function replaceAll(text, find, replace, caseInsensitive) {
6
+ return text.replace(new RegExp(escapeRegex(find), `${caseInsensitive ? "i" : ""}g`), replace);
7
+ }
8
+
9
+ /**
10
+ * Generate markup for a raw string where a particular text is wrapped with some tag, by default `<b>` (bold) tag.
11
+ * All inputs to this function are considered literal text, and special characters will always be escaped.
12
+ * @param {string} text The text to add highlighting to
13
+ * @param {string} textToHighlight The text which should be highlighted
14
+ * @return {string} the markup HTML which contains all occurrances of the input text surrounded with a `<b>` tag.
15
+ */
16
+ function generateHighlightedMarkup(text, textToHighlight) {
17
+ if (!text || !textToHighlight) {
18
+ return text;
19
+ }
20
+ // a token is some string that does not appear in either of the input strings
21
+ // repeat the token until it does not appear in the string
22
+ const makeToken = t => {
23
+ const [s, e] = t.split("");
24
+ while (text.indexOf(t) >= 0 || textToHighlight.indexOf(t) >= 0) {
25
+ t = `${s}${t}${e}`;
26
+ }
27
+ return t;
28
+ };
29
+ // It doesn't matter what characters are used as long as all 4 of them are unique
30
+ // And also that encodeXML will not change these characters
31
+ const openToken = makeToken("12");
32
+ const closeToken = makeToken("34");
33
+ // wrap every occurance of the textToHighlight using the open/close tokens (instead of markup at this point)
34
+ let result = encodeXML(replaceAll(text, textToHighlight, match => `${openToken}${match}${closeToken}`, true));
35
+ // now replace the open and close tokens with the markup that we expect
36
+ [[openToken, "<b>"], [closeToken, "</b>"]].forEach(([find, replace]) => {
37
+ result = replaceAll(result, find, replace);
38
+ });
39
+ return result;
40
+ }
41
+
42
+ export default generateHighlightedMarkup;
package/hash.txt CHANGED
@@ -1 +1 @@
1
- 4ww8NXNfQEKz/jKz4fx9NcfWBUE=
1
+ lG/1T57aPULqB5ErWOkk2B0Pejk=
@@ -1,5 +1,4 @@
1
1
  const fs = require('fs');
2
- const path = require('path');
3
2
  const mkdirp = require('mkdirp');
4
3
  const assets = require('@ui5/webcomponents-tools/assets-meta.js');
5
4
 
@@ -0,0 +1,18 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const mkdirp = require('mkdirp');
4
+ const CleanCSS = require('clean-css');
5
+
6
+ mkdirp.sync("dist/generated/css/");
7
+ fs.readdirSync("src/css/").filter(file => file.endsWith(".css")).forEach(file => {
8
+ let content = fs.readFileSync(path.join("src/css/", file));
9
+ const res = new CleanCSS().minify(`${content}`);
10
+ content = `export default {
11
+ packageName: "@ui5/webcomponents-base",
12
+ fileName: "${file}",
13
+ content: \`${res.styles}\`
14
+ };`;
15
+
16
+ fs.writeFileSync(path.join("dist/generated/css/", `${file}.js`), content);
17
+ });
18
+
@@ -1,6 +1,7 @@
1
1
  const resolve = require("resolve");
2
2
 
3
3
  const assetParametersScript = resolve.sync("@ui5/webcomponents-base/lib/generate-asset-parameters/index.js");
4
+ const stylesScript = resolve.sync("@ui5/webcomponents-base/lib/generate-styles/index.js");
4
5
  const serve = resolve.sync("@ui5/webcomponents-tools/lib/serve/index.js");
5
6
  const generateHash = resolve.sync("@ui5/webcomponents-tools/lib/hash/generate.js");
6
7
  const hashIsUpToDate = resolve.sync("@ui5/webcomponents-tools/lib/hash/upToDate.js");
@@ -12,17 +13,17 @@ const UP_TO_DATE = `node "${hashIsUpToDate}" dist/ hash.txt && echo "Up to date.
12
13
  const scripts = {
13
14
  clean: "rimraf dist && rimraf .port",
14
15
  lint: "eslint . --config config/.eslintrc.js",
15
- prepare: "nps clean integrate copy generateAssetParameters",
16
+ prepare: "nps clean integrate copy generateAssetParameters generateStyles",
16
17
  integrate: {
17
18
  default: "nps integrate.copy-used-modules integrate.copy-overlay integrate.replace-amd integrate.replace-export-true integrate.replace-export-false integrate.amd-to-es6 integrate.replace-global-core-usage integrate.esm-abs-to-rel integrate.third-party",
18
- "copy-used-modules": `node ${copyUsedModules} ./used-modules.txt dist/`,
19
+ "copy-used-modules": `node "${copyUsedModules}" ./used-modules.txt dist/`,
19
20
  "copy-overlay": `copy-and-watch "overlay/**/*.js" dist/`,
20
21
  "replace-amd": "replace-in-file sap.ui.define define dist/**/*.js",
21
22
  "replace-export-true": `replace-in-file ", /* bExport= */ true" "" dist/**/*.js`,
22
23
  "replace-export-false": `replace-in-file ", /* bExport= */ false" "" dist/**/*.js`,
23
24
  "amd-to-es6": "amdtoes6 --src=dist/ --replace --glob=**/*.js",
24
- "replace-global-core-usage": `node ${replaceGlobalCore} dist/`,
25
- "esm-abs-to-rel": `node ${esmAbsToRel} dist/ dist/`,
25
+ "replace-global-core-usage": `node "${replaceGlobalCore}" dist/`,
26
+ "esm-abs-to-rel": `node "${esmAbsToRel}" dist/ dist/`,
26
27
  "third-party": {
27
28
  default: "nps integrate.third-party.copy integrate.third-party.fix",
28
29
  copy: "mkdirp dist/sap/ui/thirdparty/ && copy-and-watch ../../node_modules/@openui5/sap.ui.core/src/sap/ui/thirdparty/caja-html-sanitizer.js dist/sap/ui/thirdparty/",
@@ -35,15 +36,17 @@ const scripts = {
35
36
  },
36
37
  copy: {
37
38
  default: "nps copy.src copy.test",
38
- src: `copy-and-watch "src/**/*.js" dist/`,
39
+ src: `copy-and-watch "src/**/*.{js,css}" dist/`,
39
40
  test: `copy-and-watch "test/**/*.*" dist/test-resources`,
40
41
  },
41
42
  generateAssetParameters: `node "${assetParametersScript}"`,
43
+ generateStyles: `node "${stylesScript}"`,
42
44
  watch: {
43
- default: 'concurrently "nps watch.test" "nps watch.src" "nps watch.bundle"',
45
+ default: 'concurrently "nps watch.test" "nps watch.src" "nps watch.bundle" "nps watch.styles"',
44
46
  src: 'nps "copy.src --watch --skip-initial-copy"',
45
47
  test: 'nps "copy.test --watch --skip-initial-copy"',
46
48
  bundle: "rollup --config config/rollup.config.js -w --environment DEV",
49
+ styles: 'chokidar "src/css/*.css" -c "nps generateStyles"'
47
50
  },
48
51
  dev: 'concurrently "nps serve" "nps watch"',
49
52
  start: "nps prepare dev",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ui5/webcomponents-base",
3
- "version": "0.33.0",
3
+ "version": "1.0.0",
4
4
  "description": "UI5 Web Components: webcomponents.base",
5
5
  "author": "SAP SE (https://www.sap.com)",
6
6
  "license": "Apache-2.0",
@@ -32,19 +32,17 @@
32
32
  "prepublishOnly": "npm run clean && npm run build"
33
33
  },
34
34
  "dependencies": {
35
- "lit-html": "2.0.0-rc.3"
35
+ "lit-html": "2.0.1"
36
36
  },
37
37
  "devDependencies": {
38
- "@ui5/webcomponents-tools": "0.33.0",
39
- "@buxlabs/amd-to-es6": "0.16.0",
40
- "@openui5/sap.ui.core": "1.87.3",
41
- "array-uniq": "^2.0.0",
42
- "chromedriver": "92.0.0",
38
+ "@buxlabs/amd-to-es6": "0.16.1",
39
+ "@openui5/sap.ui.core": "1.94.0",
40
+ "@ui5/webcomponents-tools": "1.0.0",
41
+ "chromedriver": "95.0.0",
42
+ "clean-css": "^5.2.2",
43
43
  "copy-and-watch": "^0.1.5",
44
44
  "eslint": "^7.22.0",
45
- "eslint-config-airbnb-base": "^14.2.1",
46
- "npm-run-all": "^4.1.5",
47
- "path-exists-cli": "^1.0.0",
48
- "replace-in-file": "^6.2.0"
45
+ "mkdirp": "^1.0.4",
46
+ "resolve": "^1.20.0"
49
47
  }
50
- }
48
+ }
package/src/CSP.js ADDED
@@ -0,0 +1,59 @@
1
+ const roots = new Map();
2
+ let useLinks = false;
3
+ let preloadLinks = true;
4
+
5
+ /**
6
+ * Use this function to provide the path to the directory where the css resources for the given package will be served from
7
+ *
8
+ * @public
9
+ * @param packageName name of the package that is being configured
10
+ * @param root path, accessible by the server that will serve the css resources
11
+ */
12
+ const setPackageCSSRoot = (packageName, root) => {
13
+ roots.set(packageName, root);
14
+ };
15
+
16
+ const getUrl = (packageName, path) => {
17
+ return `${roots.get(packageName)}${path}`;
18
+ };
19
+
20
+ /**
21
+ * Call this function to enable or disable the usage of <link> tags instead of <style> tags to achieve CSP compliance
22
+ * Example: "setUseLinks(true)" will unconditionally use <link> tags for all browsers;
23
+ * Example: "setUseLinks(!document.adoptedStyleSheets) will only enable the usage of <link> tags for browsers that do not support constructable stylesheets.
24
+ *
25
+ * @public
26
+ * @param use whether links will be used
27
+ */
28
+ const setUseLinks = use => {
29
+ useLinks = use;
30
+ };
31
+
32
+ /**
33
+ * Call this function to enable or disable the preloading of <link> tags.
34
+ * Note: only taken into account when <link> tags are being used.
35
+ * Note: links are being preloaded by default, so call "setPreloadLinks(false)" to opt out of this.
36
+ *
37
+ * @public
38
+ * @param preload
39
+ */
40
+ const setPreloadLinks = preload => {
41
+ preloadLinks = preload;
42
+ };
43
+
44
+ const shouldUseLinks = () => {
45
+ return useLinks;
46
+ };
47
+
48
+ const shouldPreloadLinks = () => {
49
+ return preloadLinks;
50
+ };
51
+
52
+ export {
53
+ setPackageCSSRoot,
54
+ getUrl,
55
+ setUseLinks,
56
+ setPreloadLinks,
57
+ shouldUseLinks,
58
+ shouldPreloadLinks,
59
+ };
package/src/Device.js CHANGED
@@ -91,6 +91,10 @@ const isDesktop = () => {
91
91
  return (!isTablet() && !isPhone()) || isWindows8OrAbove();
92
92
  };
93
93
 
94
+ const isCombi = () => {
95
+ return isTablet() && isDesktop();
96
+ };
97
+
94
98
  export {
95
99
  supportsTouch,
96
100
  isIE,
@@ -99,4 +103,5 @@ export {
99
103
  isPhone,
100
104
  isTablet,
101
105
  isDesktop,
106
+ isCombi,
102
107
  };
@@ -1,36 +1,37 @@
1
1
  class EventProvider {
2
2
  constructor() {
3
- this._eventRegistry = {};
3
+ this._eventRegistry = new Map();
4
4
  }
5
5
 
6
6
  attachEvent(eventName, fnFunction) {
7
7
  const eventRegistry = this._eventRegistry;
8
- let eventListeners = eventRegistry[eventName];
8
+ const eventListeners = eventRegistry.get(eventName);
9
9
 
10
10
  if (!Array.isArray(eventListeners)) {
11
- eventRegistry[eventName] = [];
12
- eventListeners = eventRegistry[eventName];
11
+ eventRegistry.set(eventName, [fnFunction]);
12
+ return;
13
13
  }
14
14
 
15
- eventListeners.push({
16
- "function": fnFunction,
17
- });
15
+ if (!eventListeners.includes(fnFunction)) {
16
+ eventListeners.push(fnFunction);
17
+ }
18
18
  }
19
19
 
20
20
  detachEvent(eventName, fnFunction) {
21
21
  const eventRegistry = this._eventRegistry;
22
- let eventListeners = eventRegistry[eventName];
22
+ const eventListeners = eventRegistry.get(eventName);
23
23
 
24
24
  if (!eventListeners) {
25
25
  return;
26
26
  }
27
+ const indexOfFnToDetach = eventListeners.indexOf(fnFunction);
27
28
 
28
- eventListeners = eventListeners.filter(event => {
29
- return event["function"] !== fnFunction; // eslint-disable-line
30
- });
29
+ if (indexOfFnToDetach !== -1) {
30
+ eventListeners.splice(indexOfFnToDetach, 1);
31
+ }
31
32
 
32
33
  if (eventListeners.length === 0) {
33
- delete eventRegistry[eventName];
34
+ eventRegistry.delete(eventName);
34
35
  }
35
36
  }
36
37
 
@@ -43,14 +44,14 @@ class EventProvider {
43
44
  */
44
45
  fireEvent(eventName, data) {
45
46
  const eventRegistry = this._eventRegistry;
46
- const eventListeners = eventRegistry[eventName];
47
+ const eventListeners = eventRegistry.get(eventName);
47
48
 
48
49
  if (!eventListeners) {
49
50
  return [];
50
51
  }
51
52
 
52
- return eventListeners.map(event => {
53
- return event["function"].call(this, data); // eslint-disable-line
53
+ return eventListeners.map(fn => {
54
+ return fn.call(this, data); // eslint-disable-line
54
55
  });
55
56
  }
56
57
 
@@ -67,24 +68,17 @@ class EventProvider {
67
68
 
68
69
  isHandlerAttached(eventName, fnFunction) {
69
70
  const eventRegistry = this._eventRegistry;
70
- const eventListeners = eventRegistry[eventName];
71
+ const eventListeners = eventRegistry.get(eventName);
71
72
 
72
73
  if (!eventListeners) {
73
74
  return false;
74
75
  }
75
76
 
76
- for (let i = 0; i < eventListeners.length; i++) {
77
- const event = eventListeners[i];
78
- if (event["function"] === fnFunction) { // eslint-disable-line
79
- return true;
80
- }
81
- }
82
-
83
- return false;
77
+ return eventListeners.includes(fnFunction);
84
78
  }
85
79
 
86
80
  hasListeners(eventName) {
87
- return !!this._eventRegistry[eventName];
81
+ return !!this._eventRegistry.get(eventName);
88
82
  }
89
83
  }
90
84
 
package/src/FontFace.js CHANGED
@@ -1,95 +1,7 @@
1
- /**
2
- * CSS font face used for the texts provided by SAP.
3
- */
4
- import createStyleInHead from "./util/createStyleInHead.js";
1
+ import { hasStyle, createStyle } from "./ManagedStyles.js";
5
2
  import { getFeature } from "./FeaturesRegistry.js";
6
-
7
- /* CDN Locations */
8
- const font72RegularWoff = `https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Regular.woff?ui5-webcomponents`;
9
- const font72RegularWoff2 = `https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Regular.woff2?ui5-webcomponents`;
10
-
11
- const font72RegularFullWoff = `https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Regular-full.woff?ui5-webcomponents`;
12
- const font72RegularFullWoff2 = `https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Regular-full.woff2?ui5-webcomponents`;
13
-
14
- const font72BoldWoff = `https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Bold.woff?ui5-webcomponents`;
15
- const font72BoldWoff2 = `https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Bold.woff2?ui5-webcomponents`;
16
-
17
- const font72BoldFullWoff = `https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Bold-full.woff?ui5-webcomponents`;
18
- const font72BoldFullWoff2 = `https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Bold-full.woff2?ui5-webcomponents`;
19
-
20
- const fontFaceCSS = `
21
- @font-face {
22
- font-family: "72";
23
- font-style: normal;
24
- font-weight: 400;
25
- src: local("72"),
26
- url(${font72RegularWoff2}) format("woff2"),
27
- url(${font72RegularWoff}) format("woff");
28
- }
29
-
30
- @font-face {
31
- font-family: "72full";
32
- font-style: normal;
33
- font-weight: 400;
34
- src: local('72-full'),
35
- url(${font72RegularFullWoff2}) format("woff2"),
36
- url(${font72RegularFullWoff}) format("woff");
37
-
38
- }
39
-
40
- @font-face {
41
- font-family: "72";
42
- font-style: normal;
43
- font-weight: 700;
44
- src: local('72-Bold'),
45
- url(${font72BoldWoff2}) format("woff2"),
46
- url(${font72BoldWoff}) format("woff");
47
- }
48
-
49
- @font-face {
50
- font-family: "72full";
51
- font-style: normal;
52
- font-weight: 700;
53
- src: local('72-Bold-full'),
54
- url(${font72BoldFullWoff2}) format("woff2"),
55
- url(${font72BoldFullWoff}) format("woff");
56
- }
57
- `;
58
-
59
- /**
60
- * Some diacritics are supported by the 72 font:
61
- * * Grave
62
- * * Acute
63
- * * Circumflex
64
- * * Tilde
65
- *
66
- * However, the following diacritics and the combination of multiple diacritics (including the supported ones) are not supported:
67
- * * Breve
68
- * * Horn
69
- * * Dot below
70
- * * Hook above
71
- *
72
- *
73
- * Override for the characters that aren't covered by the '72' font to other system fonts
74
- *
75
- * U+0102-0103: A and a with Breve
76
- * U+01A0-01A1: O and o with Horn
77
- * U+01AF-01B0: U and u with Horn
78
- * U+1EA0-1EB7: A and a with diacritics that are not supported by the font and combination of multiple diacritics
79
- * U+1EB8-1EC7: E and e with diacritics that are not supported by the font and combination of multiple diacritics
80
- * U+1EC8-1ECB: I and i with diacritics that are not supported by the font and combination of multiple diacritics
81
- * U+1ECC-1EE3: O and o with diacritics that are not supported by the font and combination of multiple diacritics
82
- * U+1EE4-1EF1: U and u with diacritics that are not supported by the font and combination of multiple diacritics
83
- * U+1EF4-1EF7: Y and y with diacritics that are not supported by the font and combination of multiple diacritics
84
- *
85
- */
86
- const overrideFontFaceCSS = `
87
- @font-face {
88
- font-family: '72override';
89
- 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;
90
- src: local('Arial'), local('Helvetica'), local('sans-serif');
91
- }
92
- `;
3
+ import fontFaceCSS from "./generated/css/FontFace.css.js";
4
+ import overrideFontFaceCSS from "./generated/css/OverrideFontFace.css.js";
93
5
 
94
6
  const insertFontFace = () => {
95
7
  const OpenUI5Support = getFeature("OpenUI5Support");
@@ -104,14 +16,14 @@ const insertFontFace = () => {
104
16
  };
105
17
 
106
18
  const insertMainFontFace = () => {
107
- if (!document.querySelector(`head>style[data-ui5-font-face]`)) {
108
- createStyleInHead(fontFaceCSS, { "data-ui5-font-face": "" });
19
+ if (!hasStyle("data-ui5-font-face")) {
20
+ createStyle(fontFaceCSS, "data-ui5-font-face");
109
21
  }
110
22
  };
111
23
 
112
24
  const insertOverrideFontFace = () => {
113
- if (!document.querySelector(`head>style[data-ui5-font-face-override]`)) {
114
- createStyleInHead(overrideFontFaceCSS, { "data-ui5-font-face-override": "" });
25
+ if (!hasStyle("data-ui5-font-face-override")) {
26
+ createStyle(overrideFontFaceCSS, "data-ui5-font-face-override");
115
27
  }
116
28
  };
117
29