UNPKG

igniteui-theming

Version:

A set of Sass variables, mixins, and functions for generating palettes, typography, and elevations used by Ignite UI components.

163 lines (156 loc) 5.77 kB
import { themingImporter } from "../utils/theming-resolve.js"; import * as sass from "sass-embedded"; //#region src/generators/css.ts /** * Generate CSS custom properties for a standard palette. * * This function compiles Sass code that uses the palette() function and * @include palette() mixin, then returns the compiled CSS output. * * @example * const result = await generatePaletteCss({ * primary: '#1976d2', * secondary: '#ff9800', * surface: '#fafafa', * variant: 'light' * }); * // result.css contains :root { --ig-primary-50: ...; --ig-primary-100: ...; ... } */ async function generatePaletteCss(options) { const variant = options.variant ?? "light"; const paletteArgs = [ `$primary: ${options.primary}`, `$secondary: ${options.secondary}`, `$surface: ${options.surface}` ]; if (options.gray) paletteArgs.push(`$gray: ${options.gray}`); if (options.info) paletteArgs.push(`$info: ${options.info}`); if (options.success) paletteArgs.push(`$success: ${options.success}`); if (options.warn) paletteArgs.push(`$warn: ${options.warn}`); if (options.error) paletteArgs.push(`$error: ${options.error}`); const sassCode = ` @use 'igniteui-theming/sass/color' as *; $palette: palette( ${paletteArgs.join(",\n ")} ); @include palette($palette); `; try { const importers = options._importers ?? [themingImporter]; return { css: (await sass.compileStringAsync(sassCode, { importers, style: "expanded" })).css, description: `Generated CSS custom properties for a ${variant} palette with primary color ${options.primary}` }; } catch (error) { const message = error instanceof Error ? error.message : String(error); throw new Error(`Failed to compile palette CSS: ${message}`); } } /** * Generate CSS custom properties for a custom palette. * * This function generates Sass code for the custom palette structure * (using either shades() function or explicit values), compiles it, * and returns the CSS output. */ async function generateCustomPaletteCss(options) { const variant = options.variant ?? "light"; const { generateCustomPaletteCode } = await import("../utils/sass.js"); const sassCode = ` @use 'igniteui-theming/sass/color' as *; ${generateCustomPaletteCode({ variant, variableName: "custom", surfaceColor: options.surfaceColor, colors: options.colors }).join("\n")} @include palette($custom-palette); `; try { const importers = options._importers ?? [themingImporter]; return { css: (await sass.compileStringAsync(sassCode, { importers, style: "expanded" })).css, description: `Generated CSS custom properties for a custom ${variant} palette` }; } catch (error) { const message = error instanceof Error ? error.message : String(error); throw new Error(`Failed to compile custom palette CSS: ${message}`); } } /** * Format CSS output for display. * Adds a header comment and ensures consistent formatting. */ function formatCssOutput(css, description) { return `/* Generated by Ignite UI Theming MCP Server */ /* ${description} */ ` + css; } /** * Generate CSS custom properties for a component theme. * * This function compiles Sass code that uses the component theme function * and @include tokens() mixin, then returns the compiled CSS output. * * @example * const result = await generateComponentThemeCss({ * platform: 'webcomponents', * designSystem: 'bootstrap', * variant: 'light', * component: 'button', * tokens: { background: '#1976d2', 'text-color': 'white' }, * selector: 'igc-button' * }); * // result.css contains: igc-button { --ig-button-background: var(--ig-button-background, #1976d2); ... } */ async function generateComponentThemeCss(options) { const { COMPONENT_METADATA, getComponentTheme, getThemingSelector, SCHEMA_PRESETS } = await import("../knowledge/index.js"); const { toVariableName } = await import("../utils/sass.js"); const theme = getComponentTheme(options.component); if (!theme) throw new Error(`Unknown component: ${options.component}`); const designSystem = options.designSystem ?? "material"; const variant = options.variant ?? "light"; const themeFn = theme.themeFunctionName; const themeComponentName = COMPONENT_METADATA[options.component]?.childOf ?? options.component; const themeName = options.name ? `$${toVariableName(options.name)}` : `$custom-${themeComponentName}-theme`; const tokenArgs = [`$schema: ${SCHEMA_PRESETS[variant][designSystem]}`]; for (const [tokenName, value] of Object.entries(options.tokens)) { const stringValue = typeof value === "number" ? String(value) : value; tokenArgs.push(`$${tokenName}: ${stringValue}`); } const defaultSelectors = getThemingSelector(options.component, options.platform); const selector = options.selector || (defaultSelectors.length > 0 ? defaultSelectors[0] : options.component); const sassCode = ` @use 'igniteui-theming/sass/themes' as *; @use 'igniteui-theming/sass/themes/schemas' as *; // Custom ${themeComponentName} theme ${themeName}: ${themeFn}( ${tokenArgs.join(",\n ")} ); // Apply the theme to ${selector} ${selector} { @include tokens(${themeName}); } `; try { const importers = options._importers ?? [themingImporter]; return { css: (await sass.compileStringAsync(sassCode, { importers, style: "expanded" })).css, description: `Generated CSS custom properties for ${themeComponentName} component with ${Object.keys(options.tokens).length} token(s) using ${designSystem} design system (${variant} variant)` }; } catch (error) { const message = error instanceof Error ? error.message : String(error); throw new Error(`Failed to compile component theme CSS: ${message}`); } } //#endregion export { formatCssOutput, generateComponentThemeCss, generateCustomPaletteCss, generatePaletteCss };