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,47 +1,45 @@
1
+ //#region src/utils/result.ts
2
+ /**
3
+ * Format validation errors and warnings for display.
4
+ *
5
+ * @param result - Validation result to format
6
+ * @param options - Formatting options
7
+ * @returns Formatted markdown string
8
+ */
1
9
  function formatValidationMessages(result, options = {}) {
2
- const {
3
- includeIcons = true,
4
- includeSuggestions = true,
5
- includeTips = true
6
- } = options;
7
- const lines = [];
8
- if (result.errors.length > 0) {
9
- lines.push("**Errors:**");
10
- for (const error of result.errors) {
11
- const icon = includeIcons ? "❌ " : "";
12
- const prefix = error.field ? `\`${error.field}\`: ` : "";
13
- lines.push(`- ${icon}${prefix}${error.message}`);
14
- if (includeSuggestions && error.suggestion) {
15
- lines.push(` Suggestion: ${error.suggestion}`);
16
- }
17
- }
18
- }
19
- if (result.warnings.length > 0) {
20
- if (lines.length > 0) lines.push("");
21
- lines.push("**Warnings:**");
22
- for (const warning of result.warnings) {
23
- const icon = includeIcons ? warning.severity === "info" ? "ℹ️ " : "⚠️ " : "";
24
- const prefix = warning.field ? `\`${warning.field}\`: ` : "";
25
- lines.push(`- ${icon}${prefix}${warning.message}`);
26
- if (includeSuggestions) {
27
- if (warning.suggestedValues && warning.suggestedValues.length > 0) {
28
- lines.push(` Suggested: ${warning.suggestedValues.join(", ")}`);
29
- } else if (warning.suggestion) {
30
- lines.push(` Suggestion: ${warning.suggestion}`);
31
- }
32
- }
33
- }
34
- }
35
- if (includeTips && result.tips && result.tips.length > 0) {
36
- if (lines.length > 0) lines.push("");
37
- lines.push("**Tips:**");
38
- for (const tip of result.tips) {
39
- const icon = includeIcons ? "💡 " : "";
40
- lines.push(`- ${icon}${tip}`);
41
- }
42
- }
43
- return lines.join("\n");
10
+ const { includeIcons = true, includeSuggestions = true, includeTips = true } = options;
11
+ const lines = [];
12
+ if (result.errors.length > 0) {
13
+ lines.push("**Errors:**");
14
+ for (const error of result.errors) {
15
+ const icon = includeIcons ? "❌ " : "";
16
+ const prefix = error.field ? `\`${error.field}\`: ` : "";
17
+ lines.push(`- ${icon}${prefix}${error.message}`);
18
+ if (includeSuggestions && error.suggestion) lines.push(` Suggestion: ${error.suggestion}`);
19
+ }
20
+ }
21
+ if (result.warnings.length > 0) {
22
+ if (lines.length > 0) lines.push("");
23
+ lines.push("**Warnings:**");
24
+ for (const warning of result.warnings) {
25
+ const icon = includeIcons ? warning.severity === "info" ? "ℹ️ " : "⚠️ " : "";
26
+ const prefix = warning.field ? `\`${warning.field}\`: ` : "";
27
+ lines.push(`- ${icon}${prefix}${warning.message}`);
28
+ if (includeSuggestions) {
29
+ if (warning.suggestedValues && warning.suggestedValues.length > 0) lines.push(` Suggested: ${warning.suggestedValues.join(", ")}`);
30
+ else if (warning.suggestion) lines.push(` Suggestion: ${warning.suggestion}`);
31
+ }
32
+ }
33
+ }
34
+ if (includeTips && result.tips && result.tips.length > 0) {
35
+ if (lines.length > 0) lines.push("");
36
+ lines.push("**Tips:**");
37
+ for (const tip of result.tips) {
38
+ const icon = includeIcons ? "💡 " : "";
39
+ lines.push(`- ${icon}${tip}`);
40
+ }
41
+ }
42
+ return lines.join("\n");
44
43
  }
45
- export {
46
- formatValidationMessages
47
- };
44
+ //#endregion
45
+ export { formatValidationMessages };
@@ -1,210 +1,290 @@
1
- import "../knowledge/colors.js";
2
- import "../knowledge/component-metadata.js";
3
- import "../knowledge/custom-palettes.js";
4
1
  import { ALL_COLOR_SHADES, SHADE_LEVELS } from "./types.js";
5
- import "../knowledge/palettes.js";
6
- import "node:fs";
7
- import "node:path";
2
+ import "../knowledge/index.js";
3
+ //#region src/utils/sass.ts
4
+ /**
5
+ * Sass code generation utilities.
6
+ *
7
+ * This module provides low-level helpers for generating Sass code snippets.
8
+ * These helpers are designed to be reusable across different code generators
9
+ * (standalone tools and platform-specific theme generators).
10
+ */
11
+ /**
12
+ * Properly quote a font-family value for Sass.
13
+ * Font stacks (containing commas) need to be wrapped in quotes
14
+ * to preserve them as a single string value.
15
+ *
16
+ * Handles various input formats:
17
+ * - `Roboto` -> `'Roboto'`
18
+ * - `'Roboto'` -> `'Roboto'` (unchanged)
19
+ * - `'Titillium Web', sans-serif` -> `"'Titillium Web', sans-serif"`
20
+ * - `"Titillium Web", sans-serif` -> `'"Titillium Web", sans-serif'`
21
+ */
8
22
  function quoteFontFamily(typeface) {
9
- if (typeface.includes(",")) {
10
- const hasDoubleQuotes = typeface.includes('"');
11
- const hasSingleQuotes = typeface.includes("'");
12
- if (hasDoubleQuotes && !hasSingleQuotes) {
13
- return `'${typeface}'`;
14
- }
15
- return `"${typeface}"`;
16
- }
17
- if (typeface.startsWith("'") || typeface.startsWith('"')) {
18
- return typeface;
19
- }
20
- return `'${typeface}'`;
23
+ if (typeface.includes(",")) {
24
+ const hasDoubleQuotes = typeface.includes("\"");
25
+ const hasSingleQuotes = typeface.includes("'");
26
+ if (hasDoubleQuotes && !hasSingleQuotes) return `'${typeface}'`;
27
+ return `"${typeface}"`;
28
+ }
29
+ if (typeface.startsWith("'") || typeface.startsWith("\"")) return typeface;
30
+ return `'${typeface}'`;
21
31
  }
32
+ /**
33
+ * Convert a name to a valid Sass variable name.
34
+ *
35
+ * Transforms input string to lowercase, replaces invalid characters with hyphens,
36
+ * collapses multiple hyphens, and removes leading/trailing hyphens.
37
+ *
38
+ * @param name - The name to convert
39
+ * @returns A valid Sass variable name (without $ prefix)
40
+ * @throws Error if the input results in an empty variable name
41
+ *
42
+ * @example
43
+ * toVariableName('My Theme') // 'my-theme'
44
+ * toVariableName('DARK_THEME_v2') // 'dark-theme-v2'
45
+ */
22
46
  function toVariableName(name) {
23
- if (!name || !name.trim()) {
24
- throw new Error("Variable name cannot be empty");
25
- }
26
- const result = name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
27
- if (!result) {
28
- throw new Error(`Cannot create valid Sass variable name from: "${name}"`);
29
- }
30
- return result;
47
+ if (!name?.trim()) throw new Error("Variable name cannot be empty");
48
+ const result = name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
49
+ if (!result) throw new Error(`Cannot create valid Sass variable name from: "${name}"`);
50
+ return result;
31
51
  }
52
+ /**
53
+ * Generate a comment header for generated Sass code.
54
+ *
55
+ * @param description - Description of what the code does
56
+ * @returns Formatted Sass comment header
57
+ */
32
58
  function generateHeader(description) {
33
- return `// Generated by Ignite UI Theming MCP Server
34
- // ${description}`;
59
+ return `// Generated by Ignite UI Theming MCP Server\n// ${description}`;
35
60
  }
61
+ /**
62
+ * Generate the Sass @use statement for the theming library.
63
+ * Uses platform-specific import paths when platform is specified.
64
+ *
65
+ * @param platform - Target platform (angular or webcomponents)
66
+ * @param licensed - Whether to use the licensed @infragistics package (Angular only, defaults to false)
67
+ * @returns The appropriate @use statement for the platform
68
+ */
36
69
  function generateUseStatement(platform, licensed) {
37
- if (platform === "angular") {
38
- const packagePath = licensed ? "@infragistics/igniteui-angular" : "igniteui-angular";
39
- return `@use "${packagePath}/theming" as *;`;
40
- }
41
- return "@use 'igniteui-theming' as *;";
70
+ if (platform === "angular") return `@use "${licensed ? "@infragistics/igniteui-angular" : "igniteui-angular"}/theming" as *;`;
71
+ return "@use 'igniteui-theming' as *;";
42
72
  }
43
- const TYPOGRAPHY_PRESETS_PATH = "igniteui-theming/sass/typography/presets";
44
- const ELEVATIONS_PRESETS_PATH = "igniteui-theming/sass/elevations/presets";
73
+ /**
74
+ * Typography presets index path.
75
+ * Imports through the index to get design-system-prefixed variables
76
+ * (e.g., $material-type-scale, $indigo-type-scale).
77
+ */
78
+ var TYPOGRAPHY_PRESETS_PATH = "igniteui-theming/sass/typography/presets";
79
+ /**
80
+ * Elevations presets index path.
81
+ * Imports through the index to get design-system-prefixed variables
82
+ * (e.g., $material-elevations, $indigo-elevations).
83
+ */
84
+ var ELEVATIONS_PRESETS_PATH = "igniteui-theming/sass/elevations/presets";
85
+ /**
86
+ * Generate additional @use import statements for typography and/or elevation presets.
87
+ *
88
+ * For non-Angular platforms, preset variables like `$material-type-scale` and
89
+ * `$material-elevations` are defined in separate sub-modules that must be
90
+ * explicitly imported. Angular's `igniteui-angular/theming` re-exports all
91
+ * presets, so no additional imports are needed.
92
+ *
93
+ * These imports use the presets index files which re-forward individual
94
+ * design system modules with prefixed names (e.g., `$type-scale` becomes
95
+ * `$material-type-scale` via `@forward './material' as material-*`).
96
+ *
97
+ * @param options - Configuration for which preset imports to include
98
+ * @returns Array of @use statements (empty for Angular)
99
+ */
45
100
  function generatePresetImports(options) {
46
- if (options.platform === "angular") {
47
- return [];
48
- }
49
- const lines = [];
50
- if (options.includeTypography) {
51
- lines.push(`@use '${TYPOGRAPHY_PRESETS_PATH}' as *;`);
52
- }
53
- if (options.includeElevations) {
54
- lines.push(`@use '${ELEVATIONS_PRESETS_PATH}' as *;`);
55
- }
56
- return lines;
101
+ if (options.platform === "angular") return [];
102
+ const lines = [];
103
+ if (options.includeTypography) lines.push(`@use '${TYPOGRAPHY_PRESETS_PATH}' as *;`);
104
+ if (options.includeElevations) lines.push(`@use '${ELEVATIONS_PRESETS_PATH}' as *;`);
105
+ return lines;
57
106
  }
107
+ /**
108
+ * Generate the palette() function call code.
109
+ * Returns an object with code lines that can be joined or embedded in other code.
110
+ *
111
+ * @example
112
+ * // Basic usage - returns lines for palette definition
113
+ * const result = generatePaletteCode({ primary: '#2ab759' });
114
+ * // result.paletteDefinition: ['$custom-light-palette: palette(', ' $primary: #2ab759,', ' $surface: white', ');']
115
+ *
116
+ * @example
117
+ * // With variable references (for use in theme generators)
118
+ * const result = generatePaletteCode({
119
+ * primary: '#2ab759',
120
+ * useVariableReferences: true,
121
+ * variableName: 'my-palette'
122
+ * });
123
+ * // Uses $primary-color, $secondary-color references
124
+ */
58
125
  function generatePaletteCode(options) {
59
- const variant = options.variant ?? "light";
60
- const varName = options.variableName ? `$${options.variableName}` : `$custom-${variant}-palette`;
61
- const colorVariables = [];
62
- const paletteArgs = [];
63
- if (options.useVariableReferences) {
64
- colorVariables.push(`$primary-color: ${options.primary};`);
65
- paletteArgs.push("$primary: $primary-color");
66
- colorVariables.push(`$secondary-color: ${options.secondary};`);
67
- paletteArgs.push("$secondary: $secondary-color");
68
- colorVariables.push(`$surface-color: ${options.surface};`);
69
- paletteArgs.push("$surface: $surface-color");
70
- if (options.gray) {
71
- colorVariables.push(`$gray-color: ${options.gray};`);
72
- paletteArgs.push("$gray: $gray-color");
73
- }
74
- } else {
75
- paletteArgs.push(`$primary: ${options.primary}`);
76
- paletteArgs.push(`$secondary: ${options.secondary}`);
77
- paletteArgs.push(`$surface: ${options.surface}`);
78
- if (options.gray) paletteArgs.push(`$gray: ${options.gray}`);
79
- }
80
- if (options.info) paletteArgs.push(`$info: ${options.info}`);
81
- if (options.success) paletteArgs.push(`$success: ${options.success}`);
82
- if (options.warn) paletteArgs.push(`$warn: ${options.warn}`);
83
- if (options.error) paletteArgs.push(`$error: ${options.error}`);
84
- const paletteDefinition = [
85
- `${varName}: palette(`,
86
- ...paletteArgs.map(
87
- (arg, i) => ` ${arg}${i < paletteArgs.length - 1 ? "," : ""}`
88
- ),
89
- ");"
90
- ];
91
- return {
92
- colorVariables,
93
- paletteDefinition,
94
- variableName: varName
95
- };
126
+ const variant = options.variant ?? "light";
127
+ const varName = options.variableName ? `$${options.variableName}` : `$custom-${variant}-palette`;
128
+ const colorVariables = [];
129
+ const paletteArgs = [];
130
+ if (options.useVariableReferences) {
131
+ colorVariables.push(`$primary-color: ${options.primary};`);
132
+ paletteArgs.push("$primary: $primary-color");
133
+ colorVariables.push(`$secondary-color: ${options.secondary};`);
134
+ paletteArgs.push("$secondary: $secondary-color");
135
+ colorVariables.push(`$surface-color: ${options.surface};`);
136
+ paletteArgs.push("$surface: $surface-color");
137
+ if (options.gray) {
138
+ colorVariables.push(`$gray-color: ${options.gray};`);
139
+ paletteArgs.push("$gray: $gray-color");
140
+ }
141
+ } else {
142
+ paletteArgs.push(`$primary: ${options.primary}`);
143
+ paletteArgs.push(`$secondary: ${options.secondary}`);
144
+ paletteArgs.push(`$surface: ${options.surface}`);
145
+ if (options.gray) paletteArgs.push(`$gray: ${options.gray}`);
146
+ }
147
+ if (options.info) paletteArgs.push(`$info: ${options.info}`);
148
+ if (options.success) paletteArgs.push(`$success: ${options.success}`);
149
+ if (options.warn) paletteArgs.push(`$warn: ${options.warn}`);
150
+ if (options.error) paletteArgs.push(`$error: ${options.error}`);
151
+ return {
152
+ colorVariables,
153
+ paletteDefinition: [
154
+ `${varName}: palette(`,
155
+ ...paletteArgs.map((arg, i) => ` ${arg}${i < paletteArgs.length - 1 ? "," : ""}`),
156
+ ");"
157
+ ],
158
+ variableName: varName
159
+ };
96
160
  }
161
+ /**
162
+ * Generate the typography() mixin call code.
163
+ * Returns an array of lines that can be joined or embedded in other code.
164
+ */
97
165
  function generateTypographyCode(options) {
98
- const indent = options.indent ?? "";
99
- return [
100
- `${indent}@include typography(`,
101
- `${indent} $font-family: ${quoteFontFamily(options.fontFamily)},`,
102
- `${indent} $type-scale: ${options.typeScaleVar}`,
103
- `${indent});`
104
- ];
166
+ const indent = options.indent ?? "";
167
+ return [
168
+ `${indent}@include typography(`,
169
+ `${indent} $font-family: ${quoteFontFamily(options.fontFamily)},`,
170
+ `${indent} $type-scale: ${options.typeScaleVar}`,
171
+ `${indent});`
172
+ ];
105
173
  }
174
+ /**
175
+ * Generate the elevations() mixin call code.
176
+ * Returns an array of lines that can be joined or embedded in other code.
177
+ */
106
178
  function generateElevationsCode(options) {
107
- const indent = options.indent ?? "";
108
- return [`${indent}@include elevations(${options.elevationsVar});`];
179
+ return [`${options.indent ?? ""}@include elevations(${options.elevationsVar});`];
109
180
  }
181
+ /**
182
+ * Generates Sass code for a custom handmade palette.
183
+ *
184
+ * This function creates a Sass map palette structure that can use either:
185
+ * - The `shades()` function for auto-generating shades from a base color
186
+ * - Explicit shade maps with manual control over each shade value
187
+ *
188
+ * @example
189
+ * // Generate palette with mixed modes
190
+ * const lines = generateCustomPaletteCode({
191
+ * variant: 'light',
192
+ * variableName: 'my-brand',
193
+ * surfaceColor: '#fafafa',
194
+ * colors: {
195
+ * primary: { mode: 'explicit', shades: { '50': '#e6eff8', ... } },
196
+ * secondary: { mode: 'shades', baseColor: '#f7bd32' },
197
+ * // ...
198
+ * }
199
+ * });
200
+ */
110
201
  function generateCustomPaletteCode(options) {
111
- const variant = options.variant ?? "light";
112
- const varName = options.variableName ?? `custom-${variant}`;
113
- const lines = [];
114
- lines.push(`$${varName}-palette: (`);
115
- const colorGroups = [
116
- {
117
- name: "primary",
118
- def: options.colors.primary,
119
- shades: ALL_COLOR_SHADES,
120
- isGray: false
121
- },
122
- {
123
- name: "secondary",
124
- def: options.colors.secondary,
125
- shades: ALL_COLOR_SHADES,
126
- isGray: false
127
- },
128
- {
129
- name: "gray",
130
- def: options.colors.gray,
131
- shades: SHADE_LEVELS,
132
- isGray: true
133
- },
134
- {
135
- name: "surface",
136
- def: options.colors.surface,
137
- shades: ALL_COLOR_SHADES,
138
- isGray: false
139
- },
140
- {
141
- name: "info",
142
- def: options.colors.info,
143
- shades: ALL_COLOR_SHADES,
144
- isGray: false
145
- },
146
- {
147
- name: "success",
148
- def: options.colors.success,
149
- shades: ALL_COLOR_SHADES,
150
- isGray: false
151
- },
152
- {
153
- name: "warn",
154
- def: options.colors.warn,
155
- shades: ALL_COLOR_SHADES,
156
- isGray: false
157
- },
158
- {
159
- name: "error",
160
- def: options.colors.error,
161
- shades: ALL_COLOR_SHADES,
162
- isGray: false
163
- }
164
- ];
165
- for (let i = 0; i < colorGroups.length; i++) {
166
- const { name, def, shades, isGray } = colorGroups[i];
167
- if (def.mode === "shades") {
168
- const shadesListStr = shades.map((s) => `'${s}'`).join(", ");
169
- lines.push(` '${name}': shades(`);
170
- lines.push(` '${name}',`);
171
- lines.push(` ${def.baseColor},`);
172
- if (isGray && options.surfaceColor) {
173
- lines.push(` (${shadesListStr}),`);
174
- lines.push(` ${options.surfaceColor}`);
175
- } else {
176
- lines.push(` (${shadesListStr})`);
177
- }
178
- lines.push(` )${","}`);
179
- } else {
180
- lines.push(` '${name}': (`);
181
- for (let j = 0; j < shades.length; j++) {
182
- const shade = shades[j];
183
- const color = def.shades[shade];
184
- const contrast = def.contrastOverrides?.[shade];
185
- const isLastShade = j === shades.length - 1;
186
- lines.push(` '${shade}': ${color},`);
187
- const contrastValue = contrast ?? `adaptive-contrast(${color})`;
188
- lines.push(` '${shade}-contrast': ${contrastValue},`);
189
- lines.push(` '${shade}-raw': ${color}${isLastShade ? "" : ","}`);
190
- }
191
- lines.push(` )${","}`);
192
- }
193
- }
194
- lines.push(` '_meta': (`);
195
- lines.push(` 'variant': ${variant}`);
196
- lines.push(" )");
197
- lines.push(");");
198
- return lines;
202
+ const variant = options.variant ?? "light";
203
+ const varName = options.variableName ?? `custom-${variant}`;
204
+ const lines = [];
205
+ lines.push(`$${varName}-palette: (`);
206
+ const colorGroups = [
207
+ {
208
+ name: "primary",
209
+ def: options.colors.primary,
210
+ shades: ALL_COLOR_SHADES,
211
+ isGray: false
212
+ },
213
+ {
214
+ name: "secondary",
215
+ def: options.colors.secondary,
216
+ shades: ALL_COLOR_SHADES,
217
+ isGray: false
218
+ },
219
+ {
220
+ name: "gray",
221
+ def: options.colors.gray,
222
+ shades: SHADE_LEVELS,
223
+ isGray: true
224
+ },
225
+ {
226
+ name: "surface",
227
+ def: options.colors.surface,
228
+ shades: ALL_COLOR_SHADES,
229
+ isGray: false
230
+ },
231
+ {
232
+ name: "info",
233
+ def: options.colors.info,
234
+ shades: ALL_COLOR_SHADES,
235
+ isGray: false
236
+ },
237
+ {
238
+ name: "success",
239
+ def: options.colors.success,
240
+ shades: ALL_COLOR_SHADES,
241
+ isGray: false
242
+ },
243
+ {
244
+ name: "warn",
245
+ def: options.colors.warn,
246
+ shades: ALL_COLOR_SHADES,
247
+ isGray: false
248
+ },
249
+ {
250
+ name: "error",
251
+ def: options.colors.error,
252
+ shades: ALL_COLOR_SHADES,
253
+ isGray: false
254
+ }
255
+ ];
256
+ for (let i = 0; i < colorGroups.length; i++) {
257
+ const { name, def, shades, isGray } = colorGroups[i];
258
+ if (def.mode === "shades") {
259
+ const shadesListStr = shades.map((s) => `'${s}'`).join(", ");
260
+ lines.push(` '${name}': shades(`);
261
+ lines.push(` '${name}',`);
262
+ lines.push(` ${def.baseColor},`);
263
+ if (isGray && options.surfaceColor) {
264
+ lines.push(` (${shadesListStr}),`);
265
+ lines.push(` ${options.surfaceColor}`);
266
+ } else lines.push(` (${shadesListStr})`);
267
+ lines.push(` ),`);
268
+ } else {
269
+ lines.push(` '${name}': (`);
270
+ for (let j = 0; j < shades.length; j++) {
271
+ const shade = shades[j];
272
+ const color = def.shades[shade];
273
+ const contrast = def.contrastOverrides?.[shade];
274
+ const isLastShade = j === shades.length - 1;
275
+ lines.push(` '${shade}': ${color},`);
276
+ const contrastValue = contrast ?? `adaptive-contrast(${color})`;
277
+ lines.push(` '${shade}-contrast': ${contrastValue},`);
278
+ lines.push(` '${shade}-raw': ${color}${isLastShade ? "" : ","}`);
279
+ }
280
+ lines.push(` ),`);
281
+ }
282
+ }
283
+ lines.push(` '_meta': (`);
284
+ lines.push(` 'variant': ${variant}`);
285
+ lines.push(" )");
286
+ lines.push(");");
287
+ return lines;
199
288
  }
200
- export {
201
- generateCustomPaletteCode,
202
- generateElevationsCode,
203
- generateHeader,
204
- generatePaletteCode,
205
- generatePresetImports,
206
- generateTypographyCode,
207
- generateUseStatement,
208
- quoteFontFamily,
209
- toVariableName
210
- };
289
+ //#endregion
290
+ export { generateCustomPaletteCode, generateElevationsCode, generateHeader, generatePaletteCode, generatePresetImports, generateTypographyCode, generateUseStatement, quoteFontFamily, toVariableName };
@@ -0,0 +1,19 @@
1
+ import { FileImporter } from 'sass-embedded';
2
+ /**
3
+ * Root directory of the igniteui-theming package.
4
+ */
5
+ export declare const THEMING_ROOT: string;
6
+ /**
7
+ * Sass FileImporter that resolves `@use 'igniteui-theming/sass/...'`
8
+ * to the theming package's `sass/` directory.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { themingImporter } from './theming-resolve.js';
13
+ *
14
+ * const result = await sass.compileStringAsync(code, {
15
+ * importers: [themingImporter],
16
+ * });
17
+ * ```
18
+ */
19
+ export declare const themingImporter: FileImporter;
@@ -0,0 +1,57 @@
1
+ import { createRequire } from "node:module";
2
+ import * as path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ //#region src/utils/theming-resolve.ts
5
+ /**
6
+ * Theming package resolution utilities.
7
+ *
8
+ * Provides a Sass FileImporter that resolves `@use 'igniteui-theming/sass/...'`
9
+ * to the theming package's sass/ directory.
10
+ *
11
+ * Resolution strategy:
12
+ * - Dev/test mode: resolves the `igniteui-theming` package via Node module resolution
13
+ * (workspace symlink in a monorepo).
14
+ * - Built mode (dist/mcp/utils/): falls back to relative __dirname traversal
15
+ * since the built MCP lives inside the theming package and can't resolve itself.
16
+ */
17
+ var __filename = fileURLToPath(import.meta.url);
18
+ var __dirname = path.dirname(__filename);
19
+ var THEMING_SASS_PREFIX = "igniteui-theming/sass/";
20
+ /**
21
+ * Resolves the root directory of the igniteui-theming package.
22
+ */
23
+ function resolveThemingRoot() {
24
+ try {
25
+ const require = createRequire(import.meta.url);
26
+ return path.dirname(require.resolve("igniteui-theming/package.json"));
27
+ } catch {
28
+ return path.resolve(__dirname, "..", "..", "..");
29
+ }
30
+ }
31
+ /**
32
+ * Root directory of the igniteui-theming package.
33
+ */
34
+ var THEMING_ROOT = resolveThemingRoot();
35
+ /**
36
+ * Sass FileImporter that resolves `@use 'igniteui-theming/sass/...'`
37
+ * to the theming package's `sass/` directory.
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * import { themingImporter } from './theming-resolve.js';
42
+ *
43
+ * const result = await sass.compileStringAsync(code, {
44
+ * importers: [themingImporter],
45
+ * });
46
+ * ```
47
+ */
48
+ var themingImporter = { findFileUrl(url) {
49
+ if (url === "igniteui-theming/sass") return new URL(`file://${path.join(THEMING_ROOT, "sass")}/`);
50
+ if (url.startsWith(THEMING_SASS_PREFIX)) {
51
+ const subpath = url.slice(22);
52
+ return new URL(subpath, `file://${path.join(THEMING_ROOT, "sass")}/`);
53
+ }
54
+ return null;
55
+ } };
56
+ //#endregion
57
+ export { themingImporter };