igniteui-theming 25.1.0 → 25.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/dist/index.d.ts +75 -0
  2. package/dist/index.js +12 -0
  3. package/dist/json/components/bootstrap.json +1 -0
  4. package/dist/json/components/fluent.json +1 -0
  5. package/dist/json/components/indigo.json +1 -0
  6. package/dist/json/components/material.json +1 -0
  7. package/{json → dist/json}/components/themes.json +31 -1
  8. package/dist/mcp/generators/css.d.ts +7 -4
  9. package/dist/mcp/generators/css.js +129 -104
  10. package/dist/mcp/generators/sass.js +227 -254
  11. package/dist/mcp/index.js +259 -323
  12. package/dist/mcp/knowledge/color-usage.js +524 -502
  13. package/dist/mcp/knowledge/colors.js +61 -50
  14. package/dist/mcp/knowledge/component-metadata.js +697 -598
  15. package/dist/mcp/knowledge/component-themes.js +70 -57
  16. package/dist/mcp/knowledge/custom-palettes.js +4 -9
  17. package/dist/mcp/knowledge/docs/colors/guidance.js +4 -0
  18. package/dist/mcp/knowledge/docs/colors/usage.js +4 -0
  19. package/dist/mcp/knowledge/docs/layout/functions/border-radius.js +4 -0
  20. package/dist/mcp/knowledge/docs/layout/functions/pad.js +4 -0
  21. package/dist/mcp/knowledge/docs/layout/functions/sizable.js +4 -0
  22. package/dist/mcp/knowledge/docs/layout/mixins/sizable.js +4 -0
  23. package/dist/mcp/knowledge/docs/layout/mixins/sizing.js +4 -0
  24. package/dist/mcp/knowledge/docs/layout/mixins/spacing.js +4 -0
  25. package/dist/mcp/knowledge/docs/layout/overview.js +4 -0
  26. package/dist/mcp/knowledge/docs/setup/platform.js +4 -0
  27. package/dist/mcp/knowledge/elevations.d.ts +1 -1
  28. package/dist/mcp/knowledge/elevations.js +26 -12
  29. package/dist/mcp/knowledge/index.js +23 -87
  30. package/dist/mcp/knowledge/layout-docs.d.ts +1 -1
  31. package/dist/mcp/knowledge/multipliers.js +5 -0
  32. package/dist/mcp/knowledge/palettes.js +29 -17
  33. package/dist/mcp/knowledge/platforms/angular.js +98 -120
  34. package/dist/mcp/knowledge/platforms/blazor.js +39 -34
  35. package/dist/mcp/knowledge/platforms/common.js +83 -68
  36. package/dist/mcp/knowledge/platforms/index.js +265 -242
  37. package/dist/mcp/knowledge/platforms/react.js +43 -35
  38. package/dist/mcp/knowledge/platforms/webcomponents.js +266 -292
  39. package/dist/mcp/knowledge/sass-api.js +1 -0
  40. package/dist/mcp/knowledge/typography.js +13 -5
  41. package/dist/mcp/resources/index.js +1 -0
  42. package/dist/mcp/resources/presets.js +409 -508
  43. package/dist/mcp/theming/dist/json/colors/meta/multipliers.js +50 -0
  44. package/dist/mcp/theming/dist/json/colors/presets/palettes.js +85 -0
  45. package/dist/mcp/theming/dist/json/components/themes.js +5792 -0
  46. package/dist/mcp/theming/dist/json/elevations/indigo.js +29 -0
  47. package/dist/mcp/theming/dist/json/elevations/material.js +3 -0
  48. package/dist/mcp/theming/dist/json/typography/presets/typescales.js +621 -0
  49. package/dist/mcp/tools/descriptions.js +98 -154
  50. package/dist/mcp/tools/handlers/color.js +58 -56
  51. package/dist/mcp/tools/handlers/component-theme.js +163 -225
  52. package/dist/mcp/tools/handlers/component-tokens.js +159 -219
  53. package/dist/mcp/tools/handlers/custom-palette.js +138 -179
  54. package/dist/mcp/tools/handlers/elevations.js +27 -28
  55. package/dist/mcp/tools/handlers/index.js +11 -0
  56. package/dist/mcp/tools/handlers/layout.js +125 -176
  57. package/dist/mcp/tools/handlers/palette.js +105 -120
  58. package/dist/mcp/tools/handlers/platform.js +289 -311
  59. package/dist/mcp/tools/handlers/resource.js +22 -31
  60. package/dist/mcp/tools/handlers/theme.js +86 -103
  61. package/dist/mcp/tools/handlers/typography.js +29 -30
  62. package/dist/mcp/tools/index.js +13 -0
  63. package/dist/mcp/tools/schemas.js +239 -218
  64. package/dist/mcp/utils/color.js +277 -239
  65. package/dist/mcp/utils/preprocessing.js +57 -30
  66. package/dist/mcp/utils/result.js +43 -45
  67. package/dist/mcp/utils/sass.js +271 -191
  68. package/dist/mcp/utils/theming-resolve.d.ts +19 -0
  69. package/dist/mcp/utils/theming-resolve.js +57 -0
  70. package/dist/mcp/utils/types.js +96 -53
  71. package/dist/mcp/validators/custom-palette.js +218 -243
  72. package/dist/mcp/validators/index.js +3 -0
  73. package/dist/mcp/validators/palette.js +231 -229
  74. package/dist/tailwind/utilities/bootstrap.css +1 -0
  75. package/dist/tailwind/utilities/fluent.css +1 -0
  76. package/dist/tailwind/utilities/indigo.css +1 -0
  77. package/dist/tailwind/utilities/material.css +1 -0
  78. package/package.json +45 -64
  79. package/sass/json/README.md +12 -7
  80. package/sass/themes/_mixins.scss +1 -0
  81. package/sass/themes/components/button-group/_button-group-theme.scss +42 -0
  82. package/sass/themes/components/grid/_grid-theme.scss +1 -1
  83. package/sass/themes/schemas/components/dark/_button-group.scss +173 -50
  84. package/sass/themes/schemas/components/dark/_grid.scss +0 -16
  85. package/sass/themes/schemas/components/light/_button-group.scss +221 -99
  86. package/sass/themes/schemas/components/light/_grid.scss +14 -20
  87. package/LICENSE +0 -21
  88. package/README.md +0 -391
  89. package/dist/mcp/json/colors/presets/palettes.json.js +0 -13
  90. package/dist/mcp/json/components/themes.json.js +0 -143
  91. package/dist/mcp/json/elevations/indigo.json.js +0 -8
  92. package/dist/mcp/json/elevations/material.json.js +0 -8
  93. package/dist/mcp/json/typography/presets/typescales.json.js +0 -17
  94. package/dist/mcp/knowledge/docs/colors/guidance.md.js +0 -4
  95. package/dist/mcp/knowledge/docs/colors/usage.md.js +0 -4
  96. package/dist/mcp/knowledge/docs/layout/functions/border-radius.md.js +0 -4
  97. package/dist/mcp/knowledge/docs/layout/functions/pad.md.js +0 -4
  98. package/dist/mcp/knowledge/docs/layout/functions/sizable.md.js +0 -4
  99. package/dist/mcp/knowledge/docs/layout/mixins/sizable.md.js +0 -4
  100. package/dist/mcp/knowledge/docs/layout/mixins/sizing.md.js +0 -4
  101. package/dist/mcp/knowledge/docs/layout/mixins/spacing.md.js +0 -4
  102. package/dist/mcp/knowledge/docs/layout/overview.md.js +0 -4
  103. package/dist/mcp/knowledge/docs/setup/platform.md.js +0 -4
  104. package/dist/mcp/vite-env.d.ts +0 -18
  105. package/index.js +0 -5
  106. package/json/components/bootstrap.json +0 -1
  107. package/json/components/fluent.json +0 -1
  108. package/json/components/indigo.json +0 -1
  109. package/json/components/material.json +0 -1
  110. package/tailwind/utilities/bootstrap.css +0 -1
  111. package/tailwind/utilities/fluent.css +0 -1
  112. package/tailwind/utilities/indigo.css +0 -1
  113. package/tailwind/utilities/material.css +0 -1
  114. /package/{json → dist/json}/colors/meta/multipliers.json +0 -0
  115. /package/{json → dist/json}/colors/meta/palette.json +0 -0
  116. /package/{json → dist/json}/colors/presets/palettes.json +0 -0
  117. /package/{json → dist/json}/elevations/indigo.json +0 -0
  118. /package/{json → dist/json}/elevations/material.json +0 -0
  119. /package/{json → dist/json}/typography/presets/typescales.json +0 -0
  120. /package/{tailwind → dist/tailwind}/themes/base.css +0 -0
  121. /package/{tailwind → dist/tailwind}/themes/dark/bootstrap.css +0 -0
  122. /package/{tailwind → dist/tailwind}/themes/dark/fluent.css +0 -0
  123. /package/{tailwind → dist/tailwind}/themes/dark/indigo.css +0 -0
  124. /package/{tailwind → dist/tailwind}/themes/dark/material.css +0 -0
  125. /package/{tailwind → dist/tailwind}/themes/light/bootstrap.css +0 -0
  126. /package/{tailwind → dist/tailwind}/themes/light/fluent.css +0 -0
  127. /package/{tailwind → dist/tailwind}/themes/light/indigo.css +0 -0
  128. /package/{tailwind → dist/tailwind}/themes/light/material.css +0 -0
@@ -1,248 +1,250 @@
1
- import { DEFAULT_MINIMUM_CONTRAST_RATIO, analyzeSurfaceGrayColors, SUGGESTED_COLORS, analyzeColorForPalette, LUMINANCE_THRESHOLD } from "../utils/color.js";
1
+ import { LUMINANCE_THRESHOLD, SUGGESTED_COLORS, analyzeColorForPalette, analyzeSurfaceGrayColors } from "../utils/color.js";
2
2
  import { formatValidationMessages } from "../utils/result.js";
3
+ //#region src/validators/palette.ts
4
+ /**
5
+ * Palette validation logic.
6
+ * Validates surface and gray colors against the theme variant.
7
+ *
8
+ * Uses the unified ValidationResult type from result.ts while maintaining
9
+ * specialized warning types for palette-specific validation.
10
+ */
11
+ /**
12
+ * Validate surface and gray colors against the theme variant.
13
+ *
14
+ * Rules:
15
+ * - Light variant: surface should be light (luminance > 0.5), gray should be dark (luminance <= 0.5)
16
+ * - Dark variant: surface should be dark (luminance <= 0.5), gray should be light (luminance > 0.5)
17
+ *
18
+ * The gray logic is inverted because the Sass palette() function generates gray shades
19
+ * that contrast against the surface.
20
+ *
21
+ * @param input - Validation input parameters
22
+ * @returns Validation result with warnings and tips
23
+ */
3
24
  async function validatePaletteColors(input) {
4
- const {
5
- variant,
6
- surface,
7
- gray,
8
- minimumContrastRatio = DEFAULT_MINIMUM_CONTRAST_RATIO
9
- } = input;
10
- const warnings = [];
11
- const tips = [];
12
- if (!surface && !gray) {
13
- return {
14
- isValid: true,
15
- errors: [],
16
- warnings: [],
17
- tips: [],
18
- analysis: {},
19
- metadata: { analysis: {} }
20
- };
21
- }
22
- let analysis;
23
- try {
24
- analysis = await analyzeSurfaceGrayColors({ surface, gray });
25
- } catch (error) {
26
- const message = error instanceof Error ? error.message : String(error);
27
- return {
28
- isValid: false,
29
- errors: [],
30
- warnings: [
31
- {
32
- field: "surface",
33
- severity: "warning",
34
- message: `Failed to analyze colors: ${message}`
35
- }
36
- ],
37
- tips: [
38
- "Ensure color values are valid CSS colors (hex, rgb, hsl, or named colors)"
39
- ],
40
- analysis: {},
41
- metadata: { analysis: {} }
42
- };
43
- }
44
- if (surface && analysis.surface) {
45
- const surfaceWarning = validateSurfaceColor(analysis.surface, variant);
46
- if (surfaceWarning) {
47
- warnings.push(surfaceWarning);
48
- }
49
- }
50
- if (gray && analysis.gray) {
51
- const grayWarning = validateGrayColor(analysis.gray, variant);
52
- if (grayWarning) {
53
- warnings.push(grayWarning);
54
- }
55
- }
56
- if (surface && gray && analysis.contrastRatio !== void 0) {
57
- if (analysis.contrastRatio < minimumContrastRatio) {
58
- warnings.push({
59
- field: "contrast",
60
- severity: "warning",
61
- message: `Contrast ratio between surface and gray is ${analysis.contrastRatio.toFixed(2)}:1, which is below the recommended ${minimumContrastRatio}:1`,
62
- details: {
63
- contrastRatio: analysis.contrastRatio
64
- }
65
- });
66
- }
67
- }
68
- if (warnings.some((w) => w.field === "gray")) {
69
- tips.push(
70
- "Consider omitting the gray parameter to let the palette() function auto-calculate an appropriate gray base from the surface color"
71
- );
72
- }
73
- if (warnings.some((w) => w.field === "surface")) {
74
- tips.push(
75
- `For a ${variant} theme, use a ${variant === "light" ? "light" : "dark"} surface color like ${SUGGESTED_COLORS[variant].surface.slice(0, 3).join(", ")}`
76
- );
77
- }
78
- return {
79
- isValid: warnings.length === 0,
80
- errors: [],
81
- warnings,
82
- tips,
83
- analysis,
84
- metadata: { analysis }
85
- };
25
+ const { variant, surface, gray, minimumContrastRatio = 3 } = input;
26
+ const warnings = [];
27
+ const tips = [];
28
+ if (!surface && !gray) return {
29
+ isValid: true,
30
+ errors: [],
31
+ warnings: [],
32
+ tips: [],
33
+ analysis: {},
34
+ metadata: { analysis: {} }
35
+ };
36
+ let analysis;
37
+ try {
38
+ analysis = await analyzeSurfaceGrayColors({
39
+ surface,
40
+ gray
41
+ });
42
+ } catch (error) {
43
+ return {
44
+ isValid: false,
45
+ errors: [],
46
+ warnings: [{
47
+ field: "surface",
48
+ severity: "warning",
49
+ message: `Failed to analyze colors: ${error instanceof Error ? error.message : String(error)}`
50
+ }],
51
+ tips: ["Ensure color values are valid CSS colors (hex, rgb, hsl, or named colors)"],
52
+ analysis: {},
53
+ metadata: { analysis: {} }
54
+ };
55
+ }
56
+ if (surface && analysis.surface) {
57
+ const surfaceWarning = validateSurfaceColor(analysis.surface, variant);
58
+ if (surfaceWarning) warnings.push(surfaceWarning);
59
+ }
60
+ if (gray && analysis.gray) {
61
+ const grayWarning = validateGrayColor(analysis.gray, variant);
62
+ if (grayWarning) warnings.push(grayWarning);
63
+ }
64
+ if (surface && gray && analysis.contrastRatio !== void 0) {
65
+ if (analysis.contrastRatio < minimumContrastRatio) warnings.push({
66
+ field: "contrast",
67
+ severity: "warning",
68
+ message: `Contrast ratio between surface and gray is ${analysis.contrastRatio.toFixed(2)}:1, which is below the recommended ${minimumContrastRatio}:1`,
69
+ details: { contrastRatio: analysis.contrastRatio }
70
+ });
71
+ }
72
+ if (warnings.some((w) => w.field === "gray")) tips.push("Consider omitting the gray parameter to let the palette() function auto-calculate an appropriate gray base from the surface color");
73
+ if (warnings.some((w) => w.field === "surface")) tips.push(`For a ${variant} theme, use a ${variant === "light" ? "light" : "dark"} surface color like ${SUGGESTED_COLORS[variant].surface.slice(0, 3).join(", ")}`);
74
+ return {
75
+ isValid: warnings.length === 0,
76
+ errors: [],
77
+ warnings,
78
+ tips,
79
+ analysis,
80
+ metadata: { analysis }
81
+ };
86
82
  }
83
+ /**
84
+ * Validate surface color against variant.
85
+ */
87
86
  function validateSurfaceColor(surface, variant) {
88
- const expectLight = variant === "light";
89
- const isCorrect = surface.isLight === expectLight;
90
- if (isCorrect) {
91
- return null;
92
- }
93
- const colorType = surface.isLight ? "light" : "dark";
94
- const expectedType = expectLight ? "light" : "dark";
95
- return {
96
- field: "surface",
97
- severity: "warning",
98
- message: `Surface color "${surface.color}" is a ${colorType} color (luminance: ${surface.luminance.toFixed(2)}), but variant is '${variant}'. Expected a ${expectedType} surface color (luminance ${expectLight ? `> ${LUMINANCE_THRESHOLD}` : `<= ${LUMINANCE_THRESHOLD}`}).`,
99
- currentValue: surface.color,
100
- suggestedValues: SUGGESTED_COLORS[variant].surface.slice(0, 3),
101
- details: {
102
- luminance: surface.luminance,
103
- isLight: surface.isLight,
104
- expectedLuminance: expectLight ? `> ${LUMINANCE_THRESHOLD}` : `<= ${LUMINANCE_THRESHOLD}`
105
- }
106
- };
87
+ const expectLight = variant === "light";
88
+ if (surface.isLight === expectLight) return null;
89
+ const colorType = surface.isLight ? "light" : "dark";
90
+ const expectedType = expectLight ? "light" : "dark";
91
+ return {
92
+ field: "surface",
93
+ severity: "warning",
94
+ message: `Surface color "${surface.color}" is a ${colorType} color (luminance: ${surface.luminance.toFixed(2)}), but variant is '${variant}'. Expected a ${expectedType} surface color (luminance ${expectLight ? `> ${LUMINANCE_THRESHOLD}` : `<= ${LUMINANCE_THRESHOLD}`}).`,
95
+ currentValue: surface.color,
96
+ suggestedValues: SUGGESTED_COLORS[variant].surface.slice(0, 3),
97
+ details: {
98
+ luminance: surface.luminance,
99
+ isLight: surface.isLight,
100
+ expectedLuminance: expectLight ? `> ${LUMINANCE_THRESHOLD}` : `<= ${LUMINANCE_THRESHOLD}`
101
+ }
102
+ };
107
103
  }
104
+ /**
105
+ * Validate gray color against variant.
106
+ *
107
+ * Note: Gray logic is INVERTED from surface because the palette() function
108
+ * generates gray shades that need to contrast with the surface.
109
+ * - Light variant (light surface) needs dark gray base
110
+ * - Dark variant (dark surface) needs light gray base
111
+ */
108
112
  function validateGrayColor(gray, variant) {
109
- const expectLightGray = variant === "dark";
110
- const isCorrect = gray.isLight === expectLightGray;
111
- if (isCorrect) {
112
- return null;
113
- }
114
- const colorType = gray.isLight ? "light" : "dark";
115
- const expectedType = expectLightGray ? "light" : "dark";
116
- return {
117
- field: "gray",
118
- severity: "warning",
119
- message: `Gray base "${gray.color}" is a ${colorType} color (luminance: ${gray.luminance.toFixed(2)}), but variant is '${variant}'. For ${variant} themes, the gray base should be ${expectedType} (luminance ${expectLightGray ? `> ${LUMINANCE_THRESHOLD}` : `<= ${LUMINANCE_THRESHOLD}`}) to ensure proper contrast with the ${variant} surface.`,
120
- currentValue: gray.color,
121
- suggestedValues: SUGGESTED_COLORS[variant].gray.slice(0, 3),
122
- details: {
123
- luminance: gray.luminance,
124
- isLight: gray.isLight,
125
- expectedLuminance: expectLightGray ? `> ${LUMINANCE_THRESHOLD}` : `<= ${LUMINANCE_THRESHOLD}`
126
- }
127
- };
113
+ const expectLightGray = variant === "dark";
114
+ if (gray.isLight === expectLightGray) return null;
115
+ const colorType = gray.isLight ? "light" : "dark";
116
+ const expectedType = expectLightGray ? "light" : "dark";
117
+ return {
118
+ field: "gray",
119
+ severity: "warning",
120
+ message: `Gray base "${gray.color}" is a ${colorType} color (luminance: ${gray.luminance.toFixed(2)}), but variant is '${variant}'. For ${variant} themes, the gray base should be ${expectedType} (luminance ${expectLightGray ? `> ${LUMINANCE_THRESHOLD}` : `<= ${LUMINANCE_THRESHOLD}`}) to ensure proper contrast with the ${variant} surface.`,
121
+ currentValue: gray.color,
122
+ suggestedValues: SUGGESTED_COLORS[variant].gray.slice(0, 3),
123
+ details: {
124
+ luminance: gray.luminance,
125
+ isLight: gray.isLight,
126
+ expectedLuminance: expectLightGray ? `> ${LUMINANCE_THRESHOLD}` : `<= ${LUMINANCE_THRESHOLD}`
127
+ }
128
+ };
128
129
  }
130
+ /**
131
+ * Format validation result as markdown for display.
132
+ *
133
+ * @param result - Validation result to format
134
+ * @returns Markdown string with warnings and tips
135
+ */
129
136
  function formatValidationResult(result) {
130
- if (result.isValid) {
131
- return "";
132
- }
133
- return formatValidationMessages(result);
137
+ if (result.isValid) return "";
138
+ return formatValidationMessages(result);
134
139
  }
140
+ /**
141
+ * Generate Sass comment warnings for code generation.
142
+ *
143
+ * @param result - Validation result
144
+ * @returns Array of Sass comment lines
145
+ */
135
146
  function generateWarningComments(result) {
136
- if (result.isValid) {
137
- return [];
138
- }
139
- return result.warnings.map((warning) => {
140
- const paramLabel = warning.field === "contrast" ? "Contrast" : `${capitalize(warning.field)} color`;
141
- return `// ⚠️ Warning: ${paramLabel} may not be optimal for this variant`;
142
- });
147
+ if (result.isValid) return [];
148
+ return result.warnings.map((warning) => {
149
+ return `// ⚠️ Warning: ${warning.field === "contrast" ? "Contrast" : `${capitalize(warning.field)} color`} may not be optimal for this variant`;
150
+ });
143
151
  }
152
+ /**
153
+ * Capitalize the first letter of a string.
154
+ */
144
155
  function capitalize(str) {
145
- return str.charAt(0).toUpperCase() + str.slice(1);
156
+ return str.charAt(0).toUpperCase() + str.slice(1);
146
157
  }
158
+ /**
159
+ * Analyze theme colors for palette shade generation suitability.
160
+ * Checks if colors have extreme luminance that would produce poor
161
+ * automatic shade generation results with the palette() function.
162
+ *
163
+ * @param params - Theme colors to analyze
164
+ * @returns Analysis result with suitability status and any problematic colors
165
+ */
147
166
  async function analyzeThemeColorsForPalette(params) {
148
- const colors = {};
149
- const problematicColors = [];
150
- colors.primary = await analyzeColorForPalette(params.primary);
151
- if (!colors.primary.suitable) {
152
- problematicColors.push({
153
- name: "primary",
154
- color: params.primary,
155
- luminance: colors.primary.luminance,
156
- issue: colors.primary.issue,
157
- description: colors.primary.description
158
- });
159
- }
160
- if (params.secondary) {
161
- colors.secondary = await analyzeColorForPalette(params.secondary);
162
- if (!colors.secondary.suitable) {
163
- problematicColors.push({
164
- name: "secondary",
165
- color: params.secondary,
166
- luminance: colors.secondary.luminance,
167
- issue: colors.secondary.issue,
168
- description: colors.secondary.description
169
- });
170
- }
171
- }
172
- if (params.surface) {
173
- colors.surface = await analyzeColorForPalette(params.surface);
174
- if (!colors.surface.suitable) {
175
- problematicColors.push({
176
- name: "surface",
177
- color: params.surface,
178
- luminance: colors.surface.luminance,
179
- issue: colors.surface.issue,
180
- description: colors.surface.description
181
- });
182
- }
183
- }
184
- return {
185
- allSuitable: problematicColors.length === 0,
186
- colors,
187
- problematicColors
188
- };
167
+ const colors = {};
168
+ const problematicColors = [];
169
+ colors.primary = await analyzeColorForPalette(params.primary);
170
+ if (!colors.primary.suitable) problematicColors.push({
171
+ name: "primary",
172
+ color: params.primary,
173
+ luminance: colors.primary.luminance,
174
+ issue: colors.primary.issue,
175
+ description: colors.primary.description
176
+ });
177
+ if (params.secondary) {
178
+ colors.secondary = await analyzeColorForPalette(params.secondary);
179
+ if (!colors.secondary.suitable) problematicColors.push({
180
+ name: "secondary",
181
+ color: params.secondary,
182
+ luminance: colors.secondary.luminance,
183
+ issue: colors.secondary.issue,
184
+ description: colors.secondary.description
185
+ });
186
+ }
187
+ if (params.surface) {
188
+ colors.surface = await analyzeColorForPalette(params.surface);
189
+ if (!colors.surface.suitable) problematicColors.push({
190
+ name: "surface",
191
+ color: params.surface,
192
+ luminance: colors.surface.luminance,
193
+ issue: colors.surface.issue,
194
+ description: colors.surface.description
195
+ });
196
+ }
197
+ return {
198
+ allSuitable: problematicColors.length === 0,
199
+ colors,
200
+ problematicColors
201
+ };
189
202
  }
203
+ /**
204
+ * Format palette suitability warnings as markdown table.
205
+ *
206
+ * @param result - Suitability analysis result
207
+ * @returns Formatted markdown string with warnings table and recommendations
208
+ */
190
209
  function formatPaletteSuitabilityWarnings(result) {
191
- if (result.allSuitable) {
192
- return "";
193
- }
194
- const lines = [];
195
- lines.push("**Color Luminance Warnings:**");
196
- lines.push("");
197
- lines.push(
198
- "The following colors have extreme luminance values that may produce suboptimal shade generation:"
199
- );
200
- lines.push("");
201
- lines.push("| Color | Value | Luminance | Issue |");
202
- lines.push("|-------|-------|-----------|-------|");
203
- for (const pc of result.problematicColors) {
204
- const issueText = pc.issue === "too-light" ? "Too light - darker shades (600-900) will appear washed out" : "Too dark - lighter shades (50-200) will lack contrast range";
205
- lines.push(
206
- `| ${pc.name} | \`${pc.color}\` | ${pc.luminance.toFixed(2)} | ${issueText} |`
207
- );
208
- }
209
- lines.push("");
210
- lines.push(
211
- "**Recommendation:** For production-quality results, use the `create_custom_palette` tool from the Ignite UI Theming MCP with explicit shade values for these colors. This gives you fine-grained control over each shade level (50-900, A100-A700)."
212
- );
213
- lines.push("");
214
- lines.push(
215
- "The generated code below uses the standard `palette()` function, which may produce limited shade ranges for the flagged colors."
216
- );
217
- return lines.join("\n");
210
+ if (result.allSuitable) return "";
211
+ const lines = [];
212
+ lines.push("**Color Luminance Warnings:**");
213
+ lines.push("");
214
+ lines.push("The following colors have extreme luminance values that may produce suboptimal shade generation:");
215
+ lines.push("");
216
+ lines.push("| Color | Value | Luminance | Issue |");
217
+ lines.push("|-------|-------|-----------|-------|");
218
+ for (const pc of result.problematicColors) {
219
+ const issueText = pc.issue === "too-light" ? "Too light - darker shades (600-900) will appear washed out" : "Too dark - lighter shades (50-200) will lack contrast range";
220
+ lines.push(`| ${pc.name} | \`${pc.color}\` | ${pc.luminance.toFixed(2)} | ${issueText} |`);
221
+ }
222
+ lines.push("");
223
+ lines.push("**Recommendation:** For production-quality results, use the `create_custom_palette` tool from the Ignite UI Theming MCP with explicit shade values for these colors. This gives you fine-grained control over each shade level (50-900, A100-A700).");
224
+ lines.push("");
225
+ lines.push("The generated code below uses the standard `palette()` function, which may produce limited shade ranges for the flagged colors.");
226
+ return lines.join("\n");
218
227
  }
228
+ /**
229
+ * Generate Sass block comment for palette suitability warnings.
230
+ * This comment is inserted into the generated Sass code to warn developers.
231
+ *
232
+ * @param result - Suitability analysis result
233
+ * @returns Array of Sass comment lines
234
+ */
219
235
  function generatePaletteSuitabilityComments(result) {
220
- if (result.allSuitable) {
221
- return [];
222
- }
223
- const lines = [];
224
- lines.push("/*");
225
- lines.push(" * ⚠️ PALETTE SUITABILITY WARNINGS");
226
- lines.push(
227
- " * The following colors have extreme luminance that may produce suboptimal shade generation:"
228
- );
229
- for (const pc of result.problematicColors) {
230
- const issueText = pc.issue === "too-light" ? "too light - darker shades may be washed out" : "too dark - lighter shades may lack range";
231
- lines.push(
232
- ` * - ${pc.name} (${pc.color}): luminance ${pc.luminance.toFixed(2)} - ${issueText}`
233
- );
234
- }
235
- lines.push(
236
- " * Consider using the create_custom_palette tool of the Ignite UI Theming MCP server with explicit shade values for better results."
237
- );
238
- lines.push(" */");
239
- return lines;
236
+ if (result.allSuitable) return [];
237
+ const lines = [];
238
+ lines.push("/*");
239
+ lines.push(" * ⚠️ PALETTE SUITABILITY WARNINGS");
240
+ lines.push(" * The following colors have extreme luminance that may produce suboptimal shade generation:");
241
+ for (const pc of result.problematicColors) {
242
+ const issueText = pc.issue === "too-light" ? "too light - darker shades may be washed out" : "too dark - lighter shades may lack range";
243
+ lines.push(` * - ${pc.name} (${pc.color}): luminance ${pc.luminance.toFixed(2)} - ${issueText}`);
244
+ }
245
+ lines.push(" * Consider using the create_custom_palette tool of the Ignite UI Theming MCP server with explicit shade values for better results.");
246
+ lines.push(" */");
247
+ return lines;
240
248
  }
241
- export {
242
- analyzeThemeColorsForPalette,
243
- formatPaletteSuitabilityWarnings,
244
- formatValidationResult,
245
- generatePaletteSuitabilityComments,
246
- generateWarningComments,
247
- validatePaletteColors
248
- };
249
+ //#endregion
250
+ export { analyzeThemeColorsForPalette, formatPaletteSuitabilityWarnings, formatValidationResult, generatePaletteSuitabilityComments, generateWarningComments, validatePaletteColors };