UNPKG

@hakxel/mantine-ui-server

Version:

MCP server for working with Mantine UI components - provides documentation, generation, and theme utilities

290 lines (289 loc) 9.1 kB
/** * Theme utilities for the Mantine UI MCP server */ /** * Generate a theme configuration based on provided settings * @param config Theme configuration * @returns Generated theme configuration */ export function generateTheme(config) { const { extension, definitions, darkMode = false } = config; switch (extension) { case 'colors': return generateColorPalettes(definitions); case 'components': return generateComponentThemes(definitions); case 'typography': return generateTypographyTheme(definitions); case 'spacing': return generateSpacingTheme(definitions); case 'radius': return generateRadiusTheme(definitions); case 'shadows': return generateShadowsTheme(definitions); case 'other': default: return definitions; } } /** * Generate color palettes based on provided definitions * @param definitions Color definitions * @returns Generated color palettes */ export function generateColorPalettes(definitions) { const palettes = {}; for (const [name, value] of Object.entries(definitions)) { if (typeof value === 'string') { // If a single color is provided, generate a palette palettes[name] = generateColorShades(value); } else if (Array.isArray(value) && value.length === 10) { // If a complete palette is provided, use it directly palettes[name] = value; } } return palettes; } /** * Generate color shades from a base color * @param baseColor Base color in hex format * @returns Array of 10 color shades */ export function generateColorShades(baseColor) { // This is a simplified algorithm; in a real implementation, this would use // color manipulation libraries to generate proper shades const hexToRgb = (hex) => { const r = parseInt(hex.slice(1, 3), 16); const g = parseInt(hex.slice(3, 5), 16); const b = parseInt(hex.slice(5, 7), 16); return [r, g, b]; }; const rgbToHex = (r, g, b) => { return `#${Math.round(r).toString(16).padStart(2, '0')}${Math.round(g).toString(16).padStart(2, '0')}${Math.round(b).toString(16).padStart(2, '0')}`; }; const lighten = (rgb, amount) => { return [ rgb[0] + (255 - rgb[0]) * amount, rgb[1] + (255 - rgb[1]) * amount, rgb[2] + (255 - rgb[2]) * amount ]; }; const darken = (rgb, amount) => { return [ rgb[0] * (1 - amount), rgb[1] * (1 - amount), rgb[2] * (1 - amount) ]; }; const rgb = hexToRgb(baseColor); // Generate 10 shades, with the base color at index 5 return [ rgbToHex(...lighten(rgb, 0.9)), rgbToHex(...lighten(rgb, 0.7)), rgbToHex(...lighten(rgb, 0.5)), rgbToHex(...lighten(rgb, 0.3)), rgbToHex(...lighten(rgb, 0.1)), baseColor, rgbToHex(...darken(rgb, 0.1)), rgbToHex(...darken(rgb, 0.2)), rgbToHex(...darken(rgb, 0.3)), rgbToHex(...darken(rgb, 0.4)) ]; } /** * Generate component theme configurations * @param definitions Component theme definitions * @returns Generated component theme configurations */ export function generateComponentThemes(definitions) { const componentThemes = {}; for (const [component, config] of Object.entries(definitions)) { componentThemes[component] = { defaultProps: config.defaultProps || {}, styles: (theme) => ({ root: { ...(config.styles?.root || {}) }, ...(config.styles || {}) }), variants: config.variants || {} }; } return { components: componentThemes }; } /** * Generate typography theme configuration * @param definitions Typography definitions * @returns Generated typography theme */ export function generateTypographyTheme(definitions) { return { fontFamily: definitions.fontFamily || undefined, fontFamilyMonospace: definitions.fontFamilyMonospace || undefined, headings: definitions.headings || undefined, fontSizes: definitions.fontSizes || undefined, lineHeights: definitions.lineHeights || undefined, }; } /** * Generate spacing theme configuration * @param definitions Spacing definitions * @returns Generated spacing theme */ export function generateSpacingTheme(definitions) { return { spacing: definitions.values || definitions }; } /** * Generate radius theme configuration * @param definitions Radius definitions * @returns Generated radius theme */ export function generateRadiusTheme(definitions) { return { radius: definitions.values || definitions }; } /** * Generate shadows theme configuration * @param definitions Shadow definitions * @returns Generated shadows theme */ export function generateShadowsTheme(definitions) { return { shadows: definitions.values || definitions }; } /** * Generate theme for a specific component * @param config Component theme configuration * @returns Generated component theme */ export function generateComponentTheme(config) { const { component, colorScheme = 'both', baseColor, variants, customSelectors } = config; // Base theme structure const componentTheme = { defaultProps: {}, styles: (theme) => ({ root: { // Base styles for the component }, // Add custom selectors if provided ...(customSelectors || {}) }) }; // Add variants if provided if (variants && variants.length > 0) { componentTheme.variants = {}; variants.forEach(variant => { componentTheme.variants[variant.name] = (theme) => ({ root: { ...variant.styles } }); }); } // Create final theme object const themeObject = { components: { [component]: componentTheme } }; return themeObject; } /** * Generate a Mantine theme configuration * @param configs Array of theme configurations * @returns Complete Mantine theme configuration */ export function generateCompleteTheme(configs) { // Start with empty theme const theme = {}; // Apply each configuration configs.forEach(config => { const generatedConfig = generateTheme(config); // Merge the generated config into the theme if (config.extension === 'components') { theme.components = { ...theme.components, ...generatedConfig.components }; } else if (config.extension === 'colors') { theme.colors = { ...theme.colors, ...generatedConfig }; } else { // For other extensions, merge at the top level Object.assign(theme, generatedConfig); } }); return theme; } /** * Generate academic-specific theme * @returns Academic theme configuration */ export function generateAcademicTheme() { return { // Academic-focused typography fontFamily: '"Merriweather", serif', fontFamilyMonospace: '"Roboto Mono", monospace', headings: { fontFamily: '"Roboto", sans-serif', fontWeight: '500', }, // Academic color palette colors: { // Example academic-focused colors academicBlue: generateColorShades('#2C3E50'), academicGreen: generateColorShades('#27AE60'), academicRed: generateColorShades('#C0392B'), academicGold: generateColorShades('#F39C12'), paperWhite: generateColorShades('#FAFAFA'), }, // Component-specific overrides components: { Paper: { defaultProps: { p: 'md', shadow: 'xs', withBorder: true, }, styles: () => ({ root: { backgroundColor: 'var(--mantine-color-paperWhite-0)', transition: 'all 200ms ease', } }) }, Text: { defaultProps: { size: 'md', }, styles: () => ({ root: { lineHeight: 1.6, } }) }, // Publication-specific components Card: { defaultProps: { shadow: 'sm', p: 'lg', radius: 'md', }, styles: () => ({ root: { backgroundColor: 'var(--mantine-color-paperWhite-0)', } }) }, }, }; }