UNPKG

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
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 };