igniteui-theming
Version:
A set of Sass variables, mixins, and functions for generating palettes, typography, and elevations used by Ignite UI components.
384 lines (372 loc) • 12.4 kB
JavaScript
import { PALETTE_PRESETS } from "../palettes.js";
import { ELEVATIONS, PALETTE_PRESETS_PATHS, TYPOGRAPHY_PRESETS_PATHS } from "./common.js";
import { generateElevationsCode, generatePaletteCode, generateTypographyCode, generateUseStatement, quoteFontFamily } from "../../utils/sass.js";
//#region src/knowledge/platforms/webcomponents.ts
/**
* Ignite UI for Web Components Platform Knowledge
*
* This module contains platform-specific information for generating
* valid Sass theme code for Ignite UI for Web Components applications.
*
* Key differences from Angular:
* - Uses `igniteui-theming` directly (not forwarded through another module)
* - No `core()` or `theme()` mixins - uses individual mixins: `palette()`, `typography()`, `elevations()`
* - Ships precompiled CSS themes, but users can install igniteui-theming for custom Sass themes
* - Components use ThemingController for runtime theme switching via CSS variables
* - Generated CSS variables follow --ig-* naming convention
*/
var WEBCOMPONENTS_PLATFORM = {
id: "webcomponents",
name: "Ignite UI for Web Components",
packageName: "igniteui-webcomponents",
themingModule: "igniteui-theming",
detectionPatterns: ["igniteui-webcomponents", "@infragistics/igniteui-webcomponents"],
rootClass: null
};
/**
* Generate the file header comment for Web Components themes.
*/
function generateWCHeader() {
return [
"// Generated by Ignite UI Theming MCP Server",
"// Platform: Ignite UI for Web Components",
""
];
}
/**
* Get the elevation preset variable for a design system.
*/
function getWCElevationPreset(designSystem) {
return ELEVATIONS[designSystem];
}
/**
* Generate import statements for a Web Components theme.
*/
function generateWCImports(options) {
const { designSystem, variant, hasCustomColors, includeTypography, includeElevations } = options;
const lines = [];
if (hasCustomColors) {
lines.push("// Import the theming module");
lines.push(generateUseStatement("webcomponents"));
if (includeTypography) {
const typographyModule = TYPOGRAPHY_PRESETS_PATHS[designSystem];
lines.push(`@use '${typographyModule}' as *;`);
}
if (includeElevations) lines.push("@use 'igniteui-theming/sass/elevations/presets' as *;");
} else {
const paletteModule = PALETTE_PRESETS_PATHS[variant][designSystem];
lines.push("// Import palette preset");
lines.push(`@use '${paletteModule}' as *;`);
lines.push("");
lines.push("// Import base theme configuration");
lines.push(generateUseStatement("webcomponents"));
if (includeTypography) {
const typographyModule = TYPOGRAPHY_PRESETS_PATHS[designSystem];
lines.push(`@use '${typographyModule}' as *;`);
}
if (includeElevations) lines.push("@use 'igniteui-theming/sass/elevations/presets' as *;");
}
return lines;
}
/**
* Generate CSS @property declarations for progress tracking.
* These are required by some components.
*/
function generateWCProgressProperties(indent = "") {
return [
`${indent}@property --_progress-integer {`,
`${indent} syntax: '<integer>';`,
`${indent} initial-value: 0;`,
`${indent} inherits: true;`,
`${indent}}`,
"",
`${indent}@property --_progress-fraction {`,
`${indent} syntax: '<integer>';`,
`${indent} initial-value: 0;`,
`${indent} inherits: true;`,
`${indent}}`
];
}
/**
* Generate :root CSS variables for theme configuration.
*/
function generateWCRootVariables(options) {
const { designSystem, variant, usePaletteMap = false, indent = "" } = options;
const lines = [];
lines.push(`${indent}:root {`);
if (usePaletteMap) {
lines.push(`${indent} --ig-theme: #{map.get($palette, '_meta', 'variant')};`);
lines.push(`${indent} --ig-theme-variant: #{$variant};`);
} else {
lines.push(`${indent} --ig-theme: ${designSystem};`);
lines.push(`${indent} --ig-theme-variant: ${variant};`);
}
lines.push(`${indent} --ig-size-small: 1;`);
lines.push(`${indent} --ig-size-medium: 2;`);
lines.push(`${indent} --ig-size-large: 3;`);
lines.push(`${indent} --ig-scrollbar-size: #{rem(16px)};`);
lines.push(`${indent}}`);
return lines;
}
/**
* Generate RTL direction support.
*/
function generateWCRtlSupport(indent = "") {
return [
`${indent}body[dir='rtl'] {`,
`${indent} --ig-dir: -1;`,
`${indent}}`
];
}
/**
* Generate scrollbar customization using palette colors.
*/
function generateWCScrollbarCustomization() {
return [
"// Scrollbar customization",
":root {",
" --ig-scrollbar-thumb-background: #{color($color: gray, $variant: 400)};",
" --ig-scrollbar-track-background: #{color($color: gray, $variant: 100)};",
"}"
];
}
/**
* Generate theming mixin calls (palette, elevations, typography, spacing).
*/
function generateWCThemingMixins(options) {
const { paletteVar, typefaceValue, elevationsVar, includeTypography, includeElevations, includeSpacing, indent = "", addComments = false } = options;
const lines = [];
if (addComments) lines.push(`${indent}// Apply palette CSS variables`);
lines.push(`${indent}@include palette(${paletteVar});`);
if (addComments) lines.push("");
if (includeElevations) {
if (addComments) lines.push(`${indent}// Apply elevation CSS variables`);
lines.push(...generateElevationsCode({
elevationsVar,
indent
}));
if (addComments) lines.push("");
}
if (includeTypography) {
if (addComments) lines.push(`${indent}// Apply typography CSS variables`);
lines.push(...generateTypographyCode({
fontFamily: typefaceValue,
typeScaleVar: "$type-scale",
indent
}));
if (addComments) lines.push("");
}
if (includeSpacing) {
if (addComments) lines.push(`${indent}// Apply spacing CSS variables`);
lines.push(`${indent}@include spacing();`);
}
return lines;
}
/**
* Generate a custom palette theme with a theme() mixin wrapper.
*/
function generateCustomPaletteTheme(template, typefaceValue) {
const { designSystem, variant, primaryColor, secondaryColor, surfaceColor, grayColor, customPaletteName = "$my-palette", includeTypography = true, includeElevations = true, includeSpacing = true } = template;
const lines = [];
const presetColors = PALETTE_PRESETS[`${variant}-${designSystem}-palette`];
const paletteResult = generatePaletteCode({
primary: primaryColor || presetColors.primary,
secondary: secondaryColor || presetColors.secondary,
surface: surfaceColor || presetColors.surface,
gray: grayColor,
variableName: customPaletteName.replace(/^\$/, ""),
useVariableReferences: true
});
lines.push("// Custom color palette");
lines.push(...paletteResult.colorVariables);
lines.push("");
lines.push(...paletteResult.paletteDefinition);
lines.push("");
lines.push("// Theme configuration");
lines.push("@mixin theme($palette, $variant) {");
lines.push(" // Root-level CSS custom properties");
lines.push(...generateWCProgressProperties(" "));
lines.push("");
lines.push(...generateWCRootVariables({
designSystem,
variant,
usePaletteMap: true,
indent: " "
}));
lines.push("");
lines.push(...generateWCRtlSupport(" "));
lines.push("");
lines.push(...generateWCThemingMixins({
paletteVar: "$palette",
typefaceValue,
elevationsVar: getWCElevationPreset(designSystem),
includeTypography,
includeElevations,
includeSpacing,
indent: " "
}));
lines.push("}");
lines.push("");
lines.push("// Apply the theme");
lines.push(`@include theme(${paletteResult.variableName}, '${variant}');`);
return lines;
}
/**
* Generate a preset palette theme (uses predefined palette from design system).
*/
function generatePresetPaletteTheme(template, typefaceValue) {
const { designSystem, variant, includeTypography = true, includeElevations = true, includeSpacing = true } = template;
const lines = [];
lines.push(...generateWCScrollbarCustomization());
lines.push("");
lines.push(...generateWCProgressProperties());
lines.push("");
lines.push(...generateWCRootVariables({
designSystem,
variant
}));
lines.push("");
lines.push(...generateWCRtlSupport());
lines.push("");
lines.push(...generateWCThemingMixins({
paletteVar: "$palette",
typefaceValue,
elevationsVar: getWCElevationPreset(designSystem),
includeTypography,
includeElevations,
includeSpacing,
addComments: true
}));
return lines;
}
/**
* Generate Sass code for a Web Components theme
*
* Web Components themes use igniteui-theming directly and call individual
* mixins (palette, typography, elevations) rather than a unified theme() mixin.
*
* This function orchestrates smaller helper functions for:
* - Header generation (generateWCHeader)
* - Import statements (generateWCImports)
* - Custom or preset palette themes
*/
function generateWebComponentsThemeSass(template) {
const { designSystem, variant, primaryColor, secondaryColor, surfaceColor, fontFamily, includeTypography = true, includeElevations = true } = template;
const typefaceValue = fontFamily ? quoteFontFamily(fontFamily) : "$typeface";
const hasCustomColors = !!(primaryColor || secondaryColor || surfaceColor);
const lines = [];
lines.push(...generateWCHeader());
lines.push(...generateWCImports({
designSystem,
variant,
hasCustomColors,
includeTypography,
includeElevations
}));
lines.push("");
if (hasCustomColors) lines.push(...generateCustomPaletteTheme(template, typefaceValue));
else lines.push(...generatePresetPaletteTheme(template, typefaceValue));
return lines.join("\n");
}
/**
* Example usage documentation
*/
var WEBCOMPONENTS_USAGE_EXAMPLES = {
basic: `
// Basic Material Light Theme for Web Components
@use 'igniteui-theming/sass/color/presets/light/material' as *;
@use 'igniteui-theming' as *;
@use 'igniteui-theming/sass/typography/presets/material' as *;
@use 'igniteui-theming/sass/elevations/presets' as *;
:root {
--ig-theme: material;
--ig-theme-variant: light;
--ig-size-small: 1;
--ig-size-medium: 2;
--ig-size-large: 3;
--ig-scrollbar-size: #{rem(16px)};
}
@include palette($palette);
@include elevations($material-elevations);
@include typography(
$font-family: $typeface,
$type-scale: $type-scale
);
@include spacing();
`,
customPalette: `
// Custom Palette Theme for Web Components
@use 'igniteui-theming' as *;
@use 'igniteui-theming/sass/typography/presets/material' as *;
@use 'igniteui-theming/sass/elevations/presets' as *;
$my-palette: palette(
$primary: #2ab759,
$secondary: #f96a88,
$surface: #ffffff
);
:root {
--ig-theme: material;
--ig-theme-variant: light;
--ig-size-small: 1;
--ig-size-medium: 2;
--ig-size-large: 3;
}
@include palette($my-palette);
@include elevations($material-elevations);
@include typography(
$font-family: $typeface,
$type-scale: $type-scale
);
@include spacing();
`,
darkTheme: `
// Dark Indigo Theme for Web Components
@use 'igniteui-theming/sass/color/presets/dark/indigo' as *;
@use 'igniteui-theming' as *;
@use 'igniteui-theming/sass/typography/presets/indigo' as *;
@use 'igniteui-theming/sass/elevations/presets' as *;
:root {
--ig-theme: indigo;
--ig-theme-variant: dark;
--ig-size-small: 1;
--ig-size-medium: 2;
--ig-size-large: 3;
}
@include palette($palette);
@include elevations($indigo-elevations);
@include typography(
$font-family: $typeface,
$type-scale: $type-scale
);
@include spacing();
`,
minimalConfig: `
// Minimal theme (palette only, no typography/elevations)
@use 'igniteui-theming/sass/color/presets/light/bootstrap' as *;
@use 'igniteui-theming' as *;
:root {
--ig-theme: bootstrap;
--ig-theme-variant: light;
}
@include palette($palette);
`
};
/**
* Runtime theme configuration for Web Components
*
* Web Components support runtime theme switching via the configureTheme() function
* and CSS variables. This is different from Angular which requires Sass recompilation.
*/
var WEBCOMPONENTS_RUNTIME_CONFIG = {
configureThemeAPI: `
import { configureTheme } from 'igniteui-webcomponents';
// Switch to dark material theme at runtime
configureTheme('material', 'dark');
// Switch to light indigo theme
configureTheme('indigo', 'light');
`,
runtimeVariables: ["--ig-theme", "--ig-theme-variant"],
themeChangeEvents: ["igc-change-theme", "igc-changed-theme"]
};
//#endregion
export { WEBCOMPONENTS_PLATFORM, WEBCOMPONENTS_RUNTIME_CONFIG, WEBCOMPONENTS_USAGE_EXAMPLES, generateWCHeader, generateWCImports, generateWCProgressProperties, generateWCRootVariables, generateWCRtlSupport, generateWCScrollbarCustomization, generateWCThemingMixins, generateWebComponentsThemeSass, getWCElevationPreset };