@equinor/fusion-react-styles
Version:
style lib inspired by @material-ui/styles
89 lines (88 loc) • 3.15 kB
JavaScript
import { styles as theme } from '@equinor/fusion-web-theme';
/**
* Deep merge helper function for runtime theme merging
*
* Recursively merges two objects, handling:
* - Nested objects (merges recursively)
* - Record types (spreads existing entries and merges new ones)
* - StyleProperty instances (replaces instead of merging)
* - Primitives (replaces with source value)
*
* @template T - The target object type
* @param target - The target object to merge into
* @param source - The source object to merge from
* @returns A new object with merged properties
*
* @internal This is an internal utility function used by createTheme
*/
function deepMerge(target, source) {
const result = { ...target };
for (const key in source) {
const sourceValue = source[key];
const targetValue = target[key];
if (sourceValue &&
typeof sourceValue === 'object' &&
!Array.isArray(sourceValue) &&
targetValue &&
typeof targetValue === 'object' &&
!Array.isArray(targetValue) &&
// Check if it's not a StyleProperty instance (they have a 'value' property)
// StyleProperty instances should be replaced, not merged
!('value' in targetValue && 'css' in targetValue && 'getAttributes' in targetValue)) {
// Both are objects - merge recursively
// For Record types, this will spread existing entries and merge new ones
// Nested objects are merged deeply to allow partial theme extensions
result[key] = deepMerge(targetValue, sourceValue);
}
else {
// Replace with source value (for primitives or StyleProperty instances)
// StyleProperty instances and primitives are replaced, not merged
result[key] = sourceValue;
}
}
return result;
}
/**
* Creates a new theme by merging custom properties with a base theme
*
* Supports deep merging for nested properties like colors, typography, etc.
* When no baseTheme is provided, uses the default Fusion theme.
*
* @template T - The extension type that extends StyleDefinition
* @param customTheme - Partial theme extension to merge with base theme
* @param baseTheme - Optional base theme to merge with (defaults to default Fusion theme)
* @returns A new theme with base theme and custom properties merged
*
* @example
* ```ts
* const myTheme = createTheme({
* colors: {
* primary: new ColorStyleProperty(...)
* }
* });
* ```
*
* @example
* ```ts
* // Merge with a custom base theme (e.g., from outer ThemeProvider)
* const extendedTheme = createTheme({
* colors: {
* ui: { background__danger: newColor }
* }
* }, outerTheme);
* ```
*/
export const createTheme = (customTheme, baseTheme) => {
const base = baseTheme ?? theme;
if (!customTheme) {
return base;
}
return deepMerge(base, customTheme);
};
/**
* Default Fusion theme object
*
* This is the default theme used when no ThemeProvider is present.
* It contains all the design tokens, colors, spacing, typography, etc.
*/
export { theme };