snapshot of https://github.com/jitsi/jitsi-meet.git @ fd1749dd28f4138aa80234fc7f311b19aaffa0e7 (2026-09-15)
This commit is contained in:
132
react/features/dynamic-branding/functions.web.ts
Normal file
132
react/features/dynamic-branding/functions.web.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
import { Theme } from '@mui/material';
|
||||
import { adaptV4Theme, createTheme } from '@mui/material/styles';
|
||||
import DOMPurify from 'dompurify';
|
||||
|
||||
import { breakpoints, colorMap, font, shape, spacing, typography } from '../base/ui/Tokens';
|
||||
import { createColorTokens } from '../base/ui/utils';
|
||||
|
||||
const DEFAULT_FONT_SIZE = 16;
|
||||
|
||||
/**
|
||||
* Sanitizes the given SVG by removing dangerous elements.
|
||||
*
|
||||
* @param {string} svg - The SVG string to clean.
|
||||
* @returns {string} The sanitized SVG string.
|
||||
*/
|
||||
export function cleanSvg(svg: string): string {
|
||||
return DOMPurify.sanitize(svg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts unitless fontSize and lineHeight values in a typography style object to rem units.
|
||||
* Backward compatibility: This conversion supports custom themes that may still override
|
||||
* typography values with numeric (pixel-based) values instead of rem strings.
|
||||
*
|
||||
* @param {Object} style - The typography style object to convert.
|
||||
* @returns {void}
|
||||
*/
|
||||
function convertTypographyToRem(style: any): void {
|
||||
if (style) {
|
||||
// Support for backward compatibility with numeric font size overrides
|
||||
if (typeof style.fontSize === 'number') {
|
||||
style.fontSize = `${style.fontSize / DEFAULT_FONT_SIZE}rem`;
|
||||
}
|
||||
// Support for backward compatibility with numeric line height overrides
|
||||
if (typeof style.lineHeight === 'number') {
|
||||
style.lineHeight = `${style.lineHeight / DEFAULT_FONT_SIZE}rem`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates MUI branding theme based on the custom theme json.
|
||||
*
|
||||
* @param {Object} customTheme - The branded custom theme.
|
||||
* @returns {Object} - The MUI theme.
|
||||
*/
|
||||
export function createMuiBrandingTheme(customTheme: Theme) {
|
||||
const {
|
||||
palette: customPalette,
|
||||
shape: customShape,
|
||||
typography: customTypography,
|
||||
breakpoints: customBreakpoints,
|
||||
spacing: customSpacing
|
||||
} = customTheme;
|
||||
|
||||
// Pass customPalette to createColorTokens so that custom colors are merged
|
||||
// BEFORE token resolution. This ensures that semantic tokens (like prejoinActionButtonPrimary)
|
||||
// that reference base tokens (like action01) will resolve to the custom color values.
|
||||
const newPalette = createColorTokens(colorMap, customPalette);
|
||||
|
||||
// Also apply overwriteRecurrsive for any direct palette key overrides that may not be
|
||||
// handled through token resolution (e.g., if customer provides semantic token names directly).
|
||||
if (customPalette) {
|
||||
overwriteRecurrsive(newPalette, customPalette);
|
||||
}
|
||||
|
||||
const newShape = { ...shape };
|
||||
|
||||
if (customShape) {
|
||||
overwriteRecurrsive(newShape, customShape);
|
||||
}
|
||||
|
||||
const newTypography = {
|
||||
font: { ...font },
|
||||
...typography
|
||||
};
|
||||
|
||||
if (customTypography) {
|
||||
overwriteRecurrsive(newTypography, customTypography);
|
||||
|
||||
// Convert typography values to rem units in case some of the overrides are using the legacy unitless format.
|
||||
// Note: We do the conversion onlt when we do have custom typography overrides. All other values are already in rem.
|
||||
for (const variant of Object.keys(newTypography)) {
|
||||
convertTypographyToRem((newTypography as Record<string, any>)[variant]);
|
||||
}
|
||||
}
|
||||
|
||||
const newBreakpoints = { ...breakpoints };
|
||||
|
||||
if (customBreakpoints) {
|
||||
overwriteRecurrsive(newBreakpoints, customBreakpoints);
|
||||
}
|
||||
|
||||
let newSpacing: any = [ ...spacing ];
|
||||
|
||||
if (customSpacing?.length) {
|
||||
newSpacing = customSpacing;
|
||||
}
|
||||
|
||||
return createTheme(adaptV4Theme({
|
||||
spacing: newSpacing,
|
||||
palette: newPalette,
|
||||
shape: newShape,
|
||||
|
||||
// @ts-ignore
|
||||
typography: newTypography,
|
||||
|
||||
// @ts-ignore
|
||||
breakpoints: newBreakpoints
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites recursively values from object 2 into object 1 based on common keys.
|
||||
* (Merges object2 into object1).
|
||||
*
|
||||
* @param {Object} obj1 - The object holding the merged values.
|
||||
* @param {Object} obj2 - The object to compare to and take values from.
|
||||
* @returns {void}
|
||||
*/
|
||||
function overwriteRecurrsive(obj1: Object, obj2: Object) {
|
||||
Object.keys(obj2).forEach(key => {
|
||||
if (obj1.hasOwnProperty(key)) {
|
||||
if (typeof obj1[key as keyof typeof obj1] === 'object') {
|
||||
overwriteRecurrsive(obj1[key as keyof typeof obj1], obj2[key as keyof typeof obj2]);
|
||||
} else {
|
||||
// @ts-ignore
|
||||
obj1[key] = obj2[key];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user