diff --git a/docs/2-advanced/01-configuration.md b/docs/2-advanced/01-configuration.md
index dd2bd817181a..9d754679a3a3 100644
--- a/docs/2-advanced/01-configuration.md
+++ b/docs/2-advanced/01-configuration.md
@@ -15,6 +15,7 @@ There are several configuration settings that affect all UI5 Web Components glob
| [secondaryCalendarType](#calendarType) | `Gregorian`, `Islamic`, `Buddhist`, `Japanese`, `Persian` | `undefined` | Default secondary calendar type to be used for date-related components | Date/time components (`ui5-date-picker`, etc.) |
| [noConflict](#noConflict) | `true`, `false` | `false` | When set to true, all events will be fired with a `ui5-` prefix only | Components that fire events (most do) |
| [formatSettings](#formatSettings) | See the [Format settings](#formatSettings) section below | `{}` | Allows to override locale-specific configuration | Date/time components (`ui5-date-picker`, etc.) |
+| [loadBaseThemingCSSVariables](#loadBaseThemingCSSVariables) | `true`, `false` | `true` | Whether to load CSS variables from `@sap-theming/theming-base-content` package | Framework |
| [fetchDefaultLanguage](#fetchDefaultLanguage) | `true`, `false` | `false` | Whether to fetch assets even for the default language | Framework |
| [defaultFontLoading](#defaultFontLoading) | `true`, `false` | `true` | Whether to fetch default font faces | Framework |
| [enableDefaultTooltips](#enableDefaultTooltips) | `true`, `false` | `true` | Whether to display default tooltips | Components (Icon, Button, RatingIndicator, etc.) |
@@ -219,6 +220,23 @@ Example:
}
```
+
+### loadBaseThemingCSSVariables
+
+
+This configuration option controls whether the framework should load the CSS variables from `@sap-theming/theming-base-content` package.
+
+Typically, you would not need to modify this setting. However, if your application provides its **own** instance or version of `@sap-theming/theming-base-content` and you prefer the framework **not** to load the built-in base theming CSS variables, you can set `loadBaseThemingCSSVariables` to `false`.
+
+Example:
+```html
+
+```
+
### defaultFontLoading
diff --git a/packages/base/src/InitialConfiguration.ts b/packages/base/src/InitialConfiguration.ts
index 93eac751df77..d1f223dc2ddf 100644
--- a/packages/base/src/InitialConfiguration.ts
+++ b/packages/base/src/InitialConfiguration.ts
@@ -24,6 +24,7 @@ type InitialConfig = {
formatSettings: FormatSettings,
fetchDefaultLanguage: boolean,
defaultFontLoading: boolean,
+ loadBaseThemingCSSVariables: boolean,
enableDefaultTooltips: boolean,
};
@@ -40,6 +41,7 @@ let initialConfig: InitialConfig = {
formatSettings: {},
fetchDefaultLanguage: false,
defaultFontLoading: true,
+ loadBaseThemingCSSVariables: true,
enableDefaultTooltips: true,
};
@@ -94,6 +96,11 @@ const getDefaultFontLoading = () => {
return initialConfig.defaultFontLoading;
};
+const getLoadBaseThemingCSSVariables = () => {
+ initConfiguration();
+ return initialConfig.loadBaseThemingCSSVariables;
+};
+
const getEnableDefaultTooltips = () => {
initConfiguration();
return initialConfig.enableDefaultTooltips;
@@ -255,6 +262,7 @@ export {
getTimezone,
getFormatSettings,
getDefaultFontLoading,
+ getLoadBaseThemingCSSVariables,
resetConfiguration,
getEnableDefaultTooltips,
};
diff --git a/packages/base/src/config/Theme.ts b/packages/base/src/config/Theme.ts
index 4f5791796a05..4e14d3e32783 100644
--- a/packages/base/src/config/Theme.ts
+++ b/packages/base/src/config/Theme.ts
@@ -1,4 +1,4 @@
-import { getTheme as getConfiguredTheme } from "../InitialConfiguration.js";
+import { getTheme as getConfiguredTheme, getLoadBaseThemingCSSVariables as getConfiguredLoadBaseThemingCSSVariables } from "../InitialConfiguration.js";
import { reRenderAllUI5Elements } from "../Render.js";
import applyTheme from "../theming/applyTheme.js";
import getThemeDesignerTheme from "../theming/getThemeDesignerTheme.js";
@@ -7,6 +7,7 @@ import { boot, isBooted } from "../Boot.js";
import { attachConfigurationReset } from "./ConfigurationReset.js";
let curTheme: string | undefined;
+let loadBaseThemingCSSVariables: boolean | undefined;
attachConfigurationReset(() => {
curTheme = undefined;
@@ -57,6 +58,36 @@ const getDefaultTheme = (): string => {
return DEFAULT_THEME;
};
+/**
+ * Returns the current configuration for loading base theming CSS variables.
+ *
+ * @public
+ * @since 2.17.0
+ * @returns {boolean}
+ */
+const getLoadBaseThemingCSSVariables = () => {
+ if (loadBaseThemingCSSVariables === undefined) {
+ loadBaseThemingCSSVariables = getConfiguredLoadBaseThemingCSSVariables();
+ }
+
+ return loadBaseThemingCSSVariables;
+};
+
+/**
+ * Configures whether to load base theming CSS variables.
+ *
+ * - When set to `true` (default), base theming CSS variables are loaded.
+ * - When set to `false`, base theming CSS variables are not loaded.
+ *
+ * **Note:** This method should be called before the boot process.
+ *
+ * @public
+ * @since 2.17.0
+ */
+const setLoadBaseThemingCSSVariables = (value: boolean) => {
+ loadBaseThemingCSSVariables = value;
+};
+
/**
* Returns if the given theme name is the one currently applied.
* @private
@@ -98,4 +129,6 @@ export {
isLegacyThemeFamily,
isLegacyThemeFamilyAsync,
getDefaultTheme,
+ getLoadBaseThemingCSSVariables,
+ setLoadBaseThemingCSSVariables,
};
diff --git a/packages/base/src/theming/applyTheme.ts b/packages/base/src/theming/applyTheme.ts
index dfc0e799c4c2..fc435e0ea439 100644
--- a/packages/base/src/theming/applyTheme.ts
+++ b/packages/base/src/theming/applyTheme.ts
@@ -5,6 +5,7 @@ import { fireThemeLoaded } from "./ThemeLoaded.js";
import { attachCustomThemeStylesToHead, getThemeRoot } from "../config/ThemeRoot.js";
import { DEFAULT_THEME } from "../generated/AssetParameters.js";
import { getCurrentRuntimeIndex } from "../Runtimes.js";
+import { getLoadBaseThemingCSSVariables } from "../config/Theme.js";
// eslint-disable-next-line
export let _lib = "ui5";
@@ -33,6 +34,10 @@ const loadComponentPackages = async (theme: string, externalThemeName?: string)
const registeredPackages = getRegisteredPackages();
const packagesStylesPromises = [...registeredPackages].map(async packageName => {
+ if (getLoadBaseThemingCSSVariables() !== true && packageName === `${BASE_THEME_PACKAGE}-raw`) {
+ return;
+ }
+
if (packageName === BASE_THEME_PACKAGE) {
return;
}
diff --git a/packages/compat/cypress/specs/Table.cy.tsx b/packages/compat/cypress/specs/Table.cy.tsx
index 516307524dc4..31b4c1bc4a91 100644
--- a/packages/compat/cypress/specs/Table.cy.tsx
+++ b/packages/compat/cypress/specs/Table.cy.tsx
@@ -509,7 +509,6 @@ describe("Table general interaction", () => {
cy.get("@popinChange")
.should(stub => {
expect(stub).to.have.been.calledTwice;
- debugger
// @ts-ignore
expect(stub.args.slice(-1)[0][0].detail.poppedColumns.length).to.equal(2);
})
diff --git a/packages/main/src/bundle.common.bootstrap.ts b/packages/main/src/bundle.common.bootstrap.ts
index bfe51ae57a00..fd2484976fd4 100644
--- a/packages/main/src/bundle.common.bootstrap.ts
+++ b/packages/main/src/bundle.common.bootstrap.ts
@@ -60,7 +60,13 @@ import { resetConfiguration } from "@ui5/webcomponents-base/dist/InitialConfigur
import { sanitizeHTML, URLListValidator } from "@ui5/webcomponents-base/dist/util/HTMLSanitizer.js";
import { getAnimationMode, setAnimationMode } from "@ui5/webcomponents-base/dist/config/AnimationMode.js";
-import { getTheme, setTheme, isLegacyThemeFamily } from "@ui5/webcomponents-base/dist/config/Theme.js";
+import {
+ getTheme,
+ setTheme,
+ isLegacyThemeFamily,
+ getLoadBaseThemingCSSVariables,
+ setLoadBaseThemingCSSVariables,
+} from "@ui5/webcomponents-base/dist/config/Theme.js";
import { getThemeRoot, setThemeRoot } from "@ui5/webcomponents-base/dist/config/ThemeRoot.js";
import { getTimezone, setTimezone } from "@ui5/webcomponents-base/dist/config/Timezone.js";
import { getLanguage, setLanguage } from "@ui5/webcomponents-base/dist/config/Language.js";
@@ -104,6 +110,8 @@ const testAssets = {
getFirstDayOfWeek,
getTimezone,
setTimezone,
+ getLoadBaseThemingCSSVariables,
+ setLoadBaseThemingCSSVariables,
},
invisibleMessage: {
announce,
diff --git a/packages/main/test/pages/Button.html b/packages/main/test/pages/Button.html
index 77fda879404d..68c5f049ab42 100644
--- a/packages/main/test/pages/Button.html
+++ b/packages/main/test/pages/Button.html
@@ -18,7 +18,7 @@
-
+
Reject
Add
diff --git a/packages/main/test/pages/theming/Themes7.html b/packages/main/test/pages/theming/Themes7.html
new file mode 100644
index 000000000000..d6932380a927
--- /dev/null
+++ b/packages/main/test/pages/theming/Themes7.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+ Theming
+
+
+
+
+
+
+
+ Some content
+
+
+
\ No newline at end of file
diff --git a/packages/main/test/pages/theming/Themes8.html b/packages/main/test/pages/theming/Themes8.html
new file mode 100644
index 000000000000..b724131f8cb4
--- /dev/null
+++ b/packages/main/test/pages/theming/Themes8.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+ Theming
+
+
+
+
+
+
+
+ Some content
+
+
+
\ No newline at end of file
diff --git a/packages/theming/package-scripts.cjs b/packages/theming/package-scripts.cjs
index 41afd71c7137..a3a68d748144 100644
--- a/packages/theming/package-scripts.cjs
+++ b/packages/theming/package-scripts.cjs
@@ -24,7 +24,11 @@ module.exports = {
src: `ui5nps-script "${TOOLS_LIB}copy-and-watch/index.js" "src/**/*.{json}" dist/`,
typescript: "tsc",
postcss: `ui5nps-script "${TOOLS_LIB}/css-processors/css-processor-themes.mjs"`,
- jsonImports: `ui5nps-script "${jsonImportsScript}" src/themes src/generated/json-imports`,
+ jsonImports: {
+ default: "ui5nps build.jsonImports.scoped build.jsonImports.raw",
+ scoped: `ui5nps-script "${jsonImportsScript}" src/themes src/generated/json-imports`,
+ raw: `ui5nps-script "${jsonImportsScript}" src/themes src/generated/json-imports -raw`,
+ }
},
generateReport: `ui5nps-script "${generateReportScript}"`,
},
diff --git a/packages/theming/src/Assets-fetch.ts b/packages/theming/src/Assets-fetch.ts
index ac3ffb58ab23..337bba7e811c 100644
--- a/packages/theming/src/Assets-fetch.ts
+++ b/packages/theming/src/Assets-fetch.ts
@@ -1,2 +1,3 @@
// The theming package provides theming assets only
import "./generated/json-imports/Themes-fetch.js";
+import "./generated/json-imports/Themes-raw-fetch.js";
diff --git a/packages/theming/src/Assets-node.ts b/packages/theming/src/Assets-node.ts
index ed2fcb45449c..7ec779239341 100644
--- a/packages/theming/src/Assets-node.ts
+++ b/packages/theming/src/Assets-node.ts
@@ -3,7 +3,7 @@
*
* It serves as an alternative to the `Assets` and `Assets-fetch` modules and supports the
* `with: { type: 'json' }` import attribute for loading JSON files.
- *
+ *
* This import attribute is required in some environments, such as Node.js with server-side rendering (SSR).
*
* Example usage:
@@ -11,3 +11,4 @@
*/
import "./generated/json-imports/Themes-node.js";
+import "./generated/json-imports/Themes-raw-node.js";
diff --git a/packages/theming/src/Assets.ts b/packages/theming/src/Assets.ts
index a8e06e58281f..87107237a47b 100644
--- a/packages/theming/src/Assets.ts
+++ b/packages/theming/src/Assets.ts
@@ -1,2 +1,3 @@
// The theming package provides theming assets only
import "./generated/json-imports/Themes.js";
+import "./generated/json-imports/Themes-raw.js";
diff --git a/packages/tools/lib/css-processors/css-processor-themes.mjs b/packages/tools/lib/css-processors/css-processor-themes.mjs
index 656402979911..3369f86bf946 100644
--- a/packages/tools/lib/css-processors/css-processor-themes.mjs
+++ b/packages/tools/lib/css-processors/css-processor-themes.mjs
@@ -9,24 +9,28 @@ import { writeFileIfChanged, getFileContent } from "./shared.mjs";
import { scopeUi5Variables, scopeThemingVariables } from "./scope-variables.mjs";
import { pathToFileURL } from "url";
-async function processThemingPackageFile(f) {
+async function processThemingPackageFile(f, scope = true) {
const selector = ':root';
const newRule = postcss.rule({ selector });
const result = await postcss().process(f.text);
result.root.walkRules(selector, rule => {
for (const decl of rule.nodes) {
- if (decl.type !== 'decl' ) {
+ if (decl.type !== 'decl') {
continue;
} else if (decl.prop.startsWith('--sapFontUrl')) {
continue;
} else if (!decl.prop.startsWith('--sap')) {
newRule.append(decl.clone());
} else {
- const originalProp = decl.prop;
- const originalValue = decl.value;
-
- newRule.append(decl.clone({ prop: originalProp.replace("--sap", "--ui5-sap"), value: `var(${originalProp}, ${originalValue})` }));
+ if (scope) {
+ const originalProp = decl.prop;
+ const originalValue = decl.value;
+
+ newRule.append(decl.clone({ prop: originalProp.replace("--sap", "--ui5-sap"), value: `var(${originalProp}, ${originalValue})` }));
+ } else {
+ newRule.append(decl.clone());
+ }
}
}
});
@@ -43,6 +47,24 @@ async function processComponentPackageFile(f, packageJSON) {
return result;
}
+async function writeProcessedContent(basePath, content, packageJSON, extension) {
+ const cssPath = basePath;
+ const jsonPath = basePath.replace(/dist[\/\\]css/, "dist/generated/assets").replace(".css", ".css.json");
+ const jsPath = basePath.replace(/dist[\/\\]css/, "src/generated/").replace(".css", extension);
+
+ // Write CSS file
+ await mkdir(path.dirname(cssPath), { recursive: true });
+ await writeFile(cssPath, content);
+
+ // Write JSON file
+ await mkdir(path.dirname(jsonPath), { recursive: true });
+ await writeFileIfChanged(jsonPath, JSON.stringify(content));
+
+ // Write JS/TS file
+ const jsContent = getFileContent(packageJSON.name, `\`${content}\``);
+ await mkdir(path.dirname(jsPath), { recursive: true });
+ await writeFileIfChanged(jsPath, jsContent);
+}
async function generate(argv) {
const tsMode = process.env.UI5_TS === "true";
@@ -55,27 +77,27 @@ async function generate(argv) {
]);
const restArgs = argv.slice(2);
- let scopingPlugin = {
+ const scopingPlugin = {
name: 'scoping',
setup(build) {
build.initialOptions.write = false;
build.onEnd(result => {
result.outputFiles.forEach(async f => {
- let newText = f.path.includes("packages/theming") ? await processThemingPackageFile(f) : await processComponentPackageFile(f, packageJSON);
-
- await mkdir(path.dirname(f.path), { recursive: true });
- writeFile(f.path, newText);
-
- // JSON
- const jsonPath = f.path.replace(/dist[\/\\]css/, "dist/generated/assets").replace(".css", ".css.json");
- await mkdir(path.dirname(jsonPath), { recursive: true });
- writeFileIfChanged(jsonPath, JSON.stringify(newText));
-
- // JS/TS
- const jsPath = f.path.replace(/dist[\/\\]css/, "src/generated/").replace(".css", extension);
- const jsContent = getFileContent(packageJSON.name, "\`" + newText + "\`");
- writeFileIfChanged(jsPath, jsContent);
+ if (f.path.includes("packages/theming")) {
+ const scopedText = await processThemingPackageFile(f);
+ const originalText = await processThemingPackageFile(f, false);
+
+ // Write scoped version
+ await writeProcessedContent(f.path, scopedText, packageJSON, extension);
+
+ // Write raw version
+ const originalPath = f.path.replace(/parameters-bundle.css$/, "parameters-bundle-raw.css");
+ await writeProcessedContent(originalPath, originalText, packageJSON, extension);
+ } else {
+ const processedText = await processComponentPackageFile(f, packageJSON);
+ await writeProcessedContent(f.path, processedText, packageJSON, extension);
+ }
});
})
},
diff --git a/packages/tools/lib/generate-json-imports/themes.js b/packages/tools/lib/generate-json-imports/themes.js
index b61d28a7226a..87f3e0e0369e 100644
--- a/packages/tools/lib/generate-json-imports/themes.js
+++ b/packages/tools/lib/generate-json-imports/themes.js
@@ -7,9 +7,10 @@ const ext = isTypeScript ? 'ts' : 'js';
const generate = async (argv) => {
const inputFolder = path.normalize(argv[2]);
- const outputFileDynamic = path.normalize(`${argv[3]}/Themes.${ext}`);
- const outputFileDynamicImportJSONAttr = path.normalize(`${argv[3]}/Themes-node.${ext}`);
- const outputFileFetchMetaResolve = path.normalize(`${argv[3]}/Themes-fetch.${ext}`);
+ const outputSuffix = argv[4] || "";
+ const outputFileDynamic = path.normalize(`${argv[3]}/Themes${outputSuffix}.${ext}`);
+ const outputFileDynamicImportJSONAttr = path.normalize(`${argv[3]}/Themes${outputSuffix}-node.${ext}`);
+ const outputFileFetchMetaResolve = path.normalize(`${argv[3]}/Themes${outputSuffix}-fetch.${ext}`);
// All supported optional themes
const allThemes = assets.themes.all;
@@ -24,9 +25,9 @@ const generate = async (argv) => {
const packageName = JSON.parse(await fs.readFile("package.json")).name;
const availableThemesArray = `[${themesOnFileSystem.map(theme => `"${theme}"`).join(", ")}]`;
- const dynamicImportLines = themesOnFileSystem.map(theme => `\t\tcase "${theme}": return (await import(/* webpackChunkName: "${packageName.replace("@", "").replace("/", "-")}-${theme.replace("_", "-")}-parameters-bundle" */"../assets/themes/${theme}/parameters-bundle.css.json")).default;`).join("\n");
- const dynamicImportJSONAttrLines = themesOnFileSystem.map(theme => `\t\tcase "${theme}": return (await import(/* webpackChunkName: "${packageName.replace("@", "").replace("/", "-")}-${theme.replace("_", "-")}-parameters-bundle" */"../assets/themes/${theme}/parameters-bundle.css.json", {with: { type: 'json'}})).default;`).join("\n");
- const fetchMetaResolveLines = themesOnFileSystem.map(theme => `\t\tcase "${theme}": return (await fetch(new URL("../assets/themes/${theme}/parameters-bundle.css.json", import.meta.url))).json();`).join("\n");
+ const dynamicImportLines = themesOnFileSystem.map(theme => `\t\tcase "${theme}": return (await import(/* webpackChunkName: "${packageName.replace("@", "").replace("/", "-")}-${theme.replace("_", "-")}-parameters-bundle" */"../assets/themes/${theme}/parameters-bundle${outputSuffix}.css.json")).default;`).join("\n");
+ const dynamicImportJSONAttrLines = themesOnFileSystem.map(theme => `\t\tcase "${theme}": return (await import(/* webpackChunkName: "${packageName.replace("@", "").replace("/", "-")}-${theme.replace("_", "-")}-parameters-bundle" */"../assets/themes/${theme}/parameters-bundle${outputSuffix}.css.json", {with: { type: 'json'}})).default;`).join("\n");
+ const fetchMetaResolveLines = themesOnFileSystem.map(theme => `\t\tcase "${theme}": return (await fetch(new URL("../assets/themes/${theme}/parameters-bundle${outputSuffix}.css.json", import.meta.url))).json();`).join("\n");
// dynamic imports file content
const contentDynamic = function (lines) {
@@ -49,7 +50,7 @@ const loadAndCheck = async (themeName) => {
};
${availableThemesArray}
- .forEach(themeName => registerThemePropertiesLoader(${packageName.split("").map(c => `"${c}"`).join(" + ")}, themeName, loadAndCheck));
+ .forEach(themeName => registerThemePropertiesLoader(${`${packageName + outputSuffix}`.split("").map(c => `"${c}"`).join(" + ")}, themeName, loadAndCheck));
`;
}