igniteui-theming
Version:
A set of Sass variables, mixins, and functions for generating palettes, typography, and elevations used by Ignite UI components.
154 lines (153 loc) • 5.68 kB
JavaScript
import { SASS_USE_ASSEMBLY_NOTE } from "../../utils/sass.js";
import { generateTheme } from "../../generators/sass.js";
import { formatCssOutput, generateThemeCss } from "../../generators/css.js";
import { analyzeThemeColorsForPalette, formatPaletteSuitabilityWarnings, formatValidationResult, generatePaletteSuitabilityComments, generateWarningComments, validatePaletteColors } from "../../validators/palette.js";
import "../../validators/index.js";
//#region src/tools/handlers/theme.ts
/**
* Handler for create_theme tool.
*/
async function handleCreateTheme(params) {
const variant = params.variant ?? "light";
const output = params.output ?? (params.platform === "angular" ? "sass" : "css");
const validation = await validatePaletteColors({
variant,
surface: params.surfaceColor
});
const suitabilityAnalysis = await analyzeThemeColorsForPalette({
primary: params.primaryColor,
secondary: params.secondaryColor,
surface: params.surfaceColor
});
if (output === "css") return handleCssOutput(params, validation, suitabilityAnalysis);
return handleSassOutput(params, validation, suitabilityAnalysis);
}
async function handleCssOutput(params, validation, suitabilityAnalysis) {
try {
const result = await generateThemeCss({
platform: params.platform,
designSystem: params.designSystem,
variant: params.variant,
primaryColor: params.primaryColor,
secondaryColor: params.secondaryColor,
surfaceColor: params.surfaceColor,
fontFamily: params.fontFamily,
includeTypography: params.includeTypography,
includeElevations: params.includeElevations,
includeSpacing: params.includeSpacing,
name: params.name
});
const formattedCss = formatCssOutput(result.css, result.description);
const responseParts = [result.description];
responseParts.push("");
responseParts.push("Output format: CSS custom properties");
if (params.platform) {
const { PLATFORM_METADATA } = await import("../../knowledge/platforms/index.js");
responseParts.push("");
responseParts.push(`Platform: ${PLATFORM_METADATA[params.platform]?.name ?? params.platform}`);
}
if (result.angularCaveat) {
responseParts.push("");
responseParts.push("⚠️ Angular note: This CSS output contains only CSS custom properties (--ig-* variables). It does not include the component-scoped class styles generated by Angular's core() and theme() mixins. For full Angular theme output use output: \"sass\".");
}
const validationText = formatValidationResult(validation);
if (validationText) {
responseParts.push("");
responseParts.push(validationText);
}
if (!suitabilityAnalysis.allSuitable) {
responseParts.push("");
responseParts.push(formatPaletteSuitabilityWarnings(suitabilityAnalysis));
}
responseParts.push("");
responseParts.push("```css");
responseParts.push(formattedCss.trimEnd());
responseParts.push("```");
return { content: [{
type: "text",
text: responseParts.join("\n")
}] };
} catch (error) {
return {
content: [{
type: "text",
text: `**Error generating CSS theme**\n\n${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
}
async function handleSassOutput(params, validation, suitabilityAnalysis) {
const result = generateTheme({
platform: params.platform,
licensed: params.licensed,
designSystem: params.designSystem,
primaryColor: params.primaryColor,
secondaryColor: params.secondaryColor,
surfaceColor: params.surfaceColor,
variant: params.variant,
name: params.name,
fontFamily: params.fontFamily,
includeTypography: params.includeTypography,
includeElevations: params.includeElevations,
includeSpacing: params.includeSpacing
});
let finalCode = result.code;
const allWarningComments = [];
if (!validation.isValid) allWarningComments.push(...generateWarningComments(validation));
if (!suitabilityAnalysis.allSuitable) allWarningComments.push(...generatePaletteSuitabilityComments(suitabilityAnalysis));
if (allWarningComments.length > 0) {
const lines = finalCode.split("\n");
const useIndex = lines.findIndex((line) => line.startsWith("@use '") || line.startsWith("@use \""));
if (useIndex > 0) {
lines.splice(useIndex, 0, ...allWarningComments, "");
finalCode = lines.join("\n");
}
}
const responseParts = [result.description];
let platformNote = "";
switch (params.platform) {
case "angular":
platformNote = "Platform: Ignite UI for Angular";
break;
case "webcomponents":
platformNote = "Platform: Ignite UI for Web Components";
break;
case "react":
platformNote = "Platform: Ignite UI for React";
break;
case "blazor":
platformNote = "Platform: Ignite UI for Blazor";
break;
case "generic":
platformNote = "Platform: Ignite UI Theming (Standalone)";
break;
default:
platformNote = "Platform: Not specified (generic output). Specify `platform` for optimized code.";
break;
}
responseParts.push("");
responseParts.push(platformNote);
const validationText = formatValidationResult(validation);
if (validationText) {
responseParts.push("");
responseParts.push(validationText);
}
if (!suitabilityAnalysis.allSuitable) {
responseParts.push("");
responseParts.push(formatPaletteSuitabilityWarnings(suitabilityAnalysis));
}
responseParts.push("");
responseParts.push(`Variables created/used: ${result.variables.join(", ")}`);
responseParts.push("");
responseParts.push("```scss");
responseParts.push(finalCode.trimEnd());
responseParts.push("```");
responseParts.push(SASS_USE_ASSEMBLY_NOTE);
return { content: [{
type: "text",
text: responseParts.join("\n")
}] };
}
//#endregion
export { handleCreateTheme };