-
Notifications
You must be signed in to change notification settings - Fork 254
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: framework-level support for CSS Custom Properties (#196)
- Loading branch information
1 parent
0934d70
commit 291829a
Showing
28 changed files
with
3,321 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,4 +34,4 @@ yarn-debug.log* | |
.yarn-integrity | ||
|
||
# Ignore default target directory for the npm package 'ui5-schemas' | ||
.tmp | ||
.tmp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
41 changes: 41 additions & 0 deletions
41
packages/base/src/sap/ui/webcomponents/base/compatibility/CSSVarsSimulation.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
let vars = new Map(); | ||
|
||
/** | ||
* Scans the given string, extracts all CSS vars from it and stores them internally | ||
* @param styleString - string containing CSS variables | ||
*/ | ||
const findCSSVars = styleString => { | ||
vars = new Map(); | ||
const couples = styleString.match(/--[^:)]+:\s*[^;}]+/g) || []; | ||
couples.forEach(couple => { | ||
const [varName, varValue] = couple.split(/:\s*/); | ||
vars.set(varName, varValue); | ||
}); | ||
}; | ||
|
||
/** | ||
* Replaces all occurrences of CSS vars with their values (and fallback values) | ||
* @param styleString - string containing CSS selectors | ||
* @returns {*} | ||
*/ | ||
const applyCSSVars = styleString => { | ||
// Replace all variables, with or without default value (default value removed too) | ||
vars.forEach((varValue, varName) => { | ||
const re = new RegExp(`var\\(\\s*${varName}.*?\\)`, "g"); | ||
styleString = styleString.replace(re, varValue); | ||
}); | ||
|
||
// Replace all unresolved variables with their default values | ||
styleString = styleString.replace(/var\(.*?,\s*(.*?)\)/g, "$1"); | ||
|
||
return styleString; | ||
}; | ||
|
||
const CSSVarsSimulation = { | ||
findCSSVars, | ||
applyCSSVars, | ||
}; | ||
|
||
window.CSSVarsSimulation = CSSVarsSimulation; | ||
|
||
export default CSSVarsSimulation; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
96 changes: 59 additions & 37 deletions
96
packages/base/src/sap/ui/webcomponents/base/theming/StyleInjection.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,47 +1,69 @@ | ||
import { getTheme } from "../Configuration"; | ||
import { attachThemeChange, getEffectiveStyle } from "../Theming"; | ||
|
||
class StyleInjection { | ||
constructor() { | ||
this.tagNamesInHead = []; | ||
this.tagsToStyleUrls = new Map(); | ||
attachThemeChange(this.updateStylesInHead.bind(this)); | ||
} | ||
import createStyleInHead from "../util/createStyleInHead"; | ||
|
||
createStyleTag(tagName, styleUrls, cssText) { | ||
if (this.tagNamesInHead.indexOf(tagName) !== -1) { | ||
return; | ||
} | ||
const injectedForTags = []; | ||
|
||
const style = document.createElement("style"); | ||
style.type = "text/css"; | ||
style.setAttribute("data-sap-source", tagName); | ||
style.innerHTML = cssText; | ||
document.head.appendChild(style); | ||
/** | ||
* Creates/updates a style element holding all CSS Custom Properties | ||
* @param cssText | ||
*/ | ||
const injectThemeProperties = cssText => { | ||
// Needed for all browsers | ||
let styleElement = document.head.querySelector(`style[ui5-webcomponents-theme-properties]`); | ||
if (styleElement) { | ||
styleElement.textContent = cssText || ""; // in case of undefined | ||
} else { | ||
styleElement = createStyleInHead(cssText, { "ui5-webcomponents-theme-properties": "" }); | ||
} | ||
|
||
this.tagNamesInHead.push(tagName); | ||
this.tagsToStyleUrls.set(tagName, styleUrls); | ||
// IE only | ||
if (window.CSSVarsSimulation) { | ||
window.CSSVarsSimulation.findCSSVars(cssText); | ||
} | ||
}; | ||
|
||
async updateStylesInHead() { | ||
if (!window.ShadyDOM) { | ||
return; | ||
} | ||
/** | ||
* Creates a style element holding the CSS for a web component (and resolves CSS Custom Properties for IE) | ||
* @param tagName | ||
* @param cssText | ||
*/ | ||
const injectWebComponentStyle = (tagName, cssText) => { | ||
if (!window.ShadyDOM) { | ||
return; | ||
} | ||
|
||
const theme = getTheme(); | ||
this.tagNamesInHead.forEach(async tagName => { | ||
const styleUrls = this.tagsToStyleUrls.get(tagName); | ||
const css = await getEffectiveStyle(theme, styleUrls, tagName); | ||
// Edge and IE | ||
if (injectedForTags.indexOf(tagName) !== -1) { | ||
return; | ||
} | ||
createStyleInHead(cssText, { "data-sap-source": tagName }); | ||
injectedForTags.push(tagName); | ||
|
||
const styleElement = document.head.querySelector(`style[data-sap-source="${tagName}"]`); | ||
// IE only | ||
if (window.CSSVarsSimulation) { | ||
const resolvedVarsCSS = window.CSSVarsSimulation.applyCSSVars(cssText); | ||
createStyleInHead(resolvedVarsCSS, { "data-sap-source-replaced-vars": tagName }); | ||
} | ||
}; | ||
|
||
if (styleElement) { | ||
styleElement.innerHTML = css || ""; // in case of undefined | ||
} else { | ||
this.createStyleTag(tagName, styleUrls, css || ""); | ||
} | ||
}); | ||
/** | ||
* Updates the style elements holding the CSS for all web components by resolving the CSS Custom properties | ||
*/ | ||
const updateWebComponentStyles = () => { | ||
if (!window.CSSVarsSimulation) { | ||
return; | ||
} | ||
} | ||
|
||
export default new StyleInjection(); | ||
// IE only | ||
injectedForTags.forEach(tagName => { | ||
const originalStyleElement = document.head.querySelector(`style[data-sap-source="${tagName}"]`); | ||
const replacedVarsStyleElement = document.head.querySelector(`style[data-sap-source-replaced-vars="${tagName}"]`); | ||
const resolvedVarsCSS = window.CSSVarsSimulation.applyCSSVars(originalStyleElement.textContent); | ||
replacedVarsStyleElement.textContent = resolvedVarsCSS; | ||
}); | ||
}; | ||
|
||
export { | ||
injectThemeProperties, | ||
injectWebComponentStyle, | ||
updateWebComponentStyles, | ||
}; |
32 changes: 32 additions & 0 deletions
32
packages/base/src/sap/ui/webcomponents/base/theming/ThemeProperties.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { fetchTextOnce } from "../util/FetchHelper"; | ||
|
||
const themeURLs = new Map(); | ||
const propertiesStyles = new Map(); | ||
|
||
const registerThemeProperties = (packageName, themeName, data) => { | ||
if (data.includes(":root")) { | ||
// inlined content | ||
propertiesStyles.set(`${packageName}_${themeName}`, data); | ||
} else { | ||
// url for fetching | ||
themeURLs.set(`${packageName}_${themeName}`, data); | ||
} | ||
}; | ||
|
||
const getThemeProperties = async (packageName, themeName) => { | ||
const style = propertiesStyles.get(`${packageName}_${themeName}`); | ||
if (style) { | ||
return style; | ||
} | ||
|
||
const data = await fetchThemeProperties(packageName, themeName); | ||
propertiesStyles.set(`${packageName}_${themeName}`, data); | ||
return data; | ||
}; | ||
|
||
const fetchThemeProperties = async (packageName, themeName) => { | ||
const url = themeURLs.get(`${packageName}_${themeName}`); | ||
return fetchTextOnce(url); | ||
}; | ||
|
||
export { registerThemeProperties, getThemeProperties }; |
18 changes: 18 additions & 0 deletions
18
packages/base/src/sap/ui/webcomponents/base/util/createStyleInHead.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/** | ||
* Creates a <style> tag in the <head> tag | ||
* @param cssText - the CSS | ||
* @param attributes - optional attributes to add to the tag | ||
* @returns {HTMLElement} | ||
*/ | ||
const createStyleInHead = (cssText, attributes = {}) => { | ||
const style = document.createElement("style"); | ||
style.type = "text/css"; | ||
|
||
Object.entries(attributes).forEach(pair => style.setAttribute(...pair)); | ||
|
||
style.textContent = cssText; | ||
document.head.appendChild(style); | ||
return style; | ||
}; | ||
|
||
export default createStyleInHead; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,3 +8,4 @@ bundle.esm.js | |
bundle.es5.js | ||
rollup.config*.js | ||
wdio.conf.js | ||
postcss.config.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
const postcssImport = require('postcss-import'); | ||
module.exports = { | ||
plugins: [ | ||
postcssImport() | ||
] | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const postcssNesting = require('postcss-nesting'); | ||
const postcssAddFallback = require('../../lib/postcss-add-fallback/index.js'); | ||
|
||
module.exports = { | ||
plugins: [ | ||
postcssNesting(), | ||
postcssAddFallback({importFrom: "./dist/themes-next/sap_fiori_3/parameters-bundle.css"}), | ||
] | ||
} |
Oops, something went wrong.