import type { AppTheme, MD3ColorSchemeTokens, MD3NeutralTones, MD3Palettes, MD3Tones } from './theme.types'; import { argbFromHex, hexFromArgb, TonalPalette, } from '@material/material-color-utilities'; /** * Generates a theme based on the provided color values. * * @param {object} options - The color options for the theme. - 主题的颜色选项。 * @param {string} options.primary - The primary color. - 主色。 * @param {string} options.secondary - The secondary color. - 次要颜色。 * @param {string} options.tertiary - The tertiary color. - 第三色。 * @param {string} options.error - The error color. - 错误颜色。 * @param {string} options.info - The info color. - 信息颜色。 * @param {string} options.warning - The warning color. - 警告颜色。 * @param {string} options.success - The success color. - 成功颜色。 * @param {string} options.neutral - The neutral color. - 中性颜色。 * @param {string} options.neutralVariant - The variant of the neutral color. - 中性颜色的变体。 * * @returns {object} - The generated theme object. - 生成的主题对象。 * @property {MD3Palettes} palette - The color palette of the theme. - 主题的颜色调色板。 * The palette includes primary, secondary, and other colors used throughout the theme. - 调色板包括主要的、次要的和主题中使用的其他颜色。 * @property {MD3Tones} palette.primary - The primary color tones. - 主色调。 * @property {MD3Tones} palette.secondary - The secondary color tones. - 次要颜色调。 * @property {MD3Tones} palette.tertiary - The tertiary color tones. - 第三色调。 * @property {MD3NeutralTones} palette.neutral - The neutral color tones. - 中性颜色调。 * @property {MD3Tones} palette.neutralVariant - The neutral variant color tones. - 中性变体颜色调。 * @property {MD3Tones} palette.error - The error color tones. - 错误颜色调。 * @property {MD3Tones} [palette.info] - The info color tones. - 信息颜色调。 * @property {MD3Tones} [palette.warning] - The warning color tones. - 警告颜色调。 * @property {MD3Tones} [palette.success] - The success color tones. - 成功颜色调。 * @property {object} [palette.common] - Common colors. - 常见颜色。 * @property {string} palette.common.black - The black color. - 黑色。 * @property {string} palette.common.white - The white color. - 白色。 * @property {MD3ColorSchemeTokens} lightScheme - The color scheme for light mode. - 亮色模式的颜色方案。 * The light scheme defines the colors used when the theme is in light mode. - 亮色模式定义了主题在亮色模式下使用的颜色。 * @property {string} lightScheme.primary - The primary color used in light mode. - 亮色模式下使用的主色。 * @property {string} lightScheme.onPrimary - The color used for text and icons on top of the primary color. - 用于主色上的文本和图标的颜色。 * @property {string} lightScheme.primaryContainer - The primary container color used in light mode. - 亮色模式下使用的主容器颜色。 * @property {string} lightScheme.onPrimaryContainer - The color used for text and icons on top of the primary container color. - 用于主容器颜色上的文本和图标的颜色。 * @property {string} lightScheme.secondary - The secondary color used in light mode. - 亮色模式下使用的次要颜色。 * @property {string} lightScheme.onSecondary - The color used for text and icons on top of the secondary color. - 用于次要颜色上的文本和图标的颜色。 * @property {string} lightScheme.secondaryContainer - The secondary container color used in light mode. - 亮色模式下使用的次要容器颜色。 * @property {string} lightScheme.onSecondaryContainer - The color used for text and icons on top of the secondary container color. - 用于次要容器颜色上的文本和图标的颜色。 * @property {string} lightScheme.tertiary - The tertiary color used in light mode. - 亮色模式下使用的第三色。 * @property {string} lightScheme.onTertiary - The color used for text and icons on top of the tertiary color. - 用于第三色上的文本和图标的颜色。 * @property {string} lightScheme.tertiaryContainer - The tertiary container color used in light mode. - 亮色模式下使用的第三色容器颜色。 * @property {string} lightScheme.onTertiaryContainer - The color used for text and icons on top of the tertiary container color. - 用于第三色容器颜色上的文本和图标的颜色。 * @property {string} lightScheme.error - The error color used in light mode. - 亮色模式下使用的错误颜色。 * @property {string} lightScheme.onError - The color used for text and icons on top of the error color. - 用于错误颜色上的文本和图标的颜色。 * @property {string} lightScheme.errorContainer - The error container color used in light mode. - 亮色模式下使用的错误容器颜色。 * @property {string} lightScheme.onErrorContainer - The color used for text and icons on top of the error container color. - 用于错误容器颜色上的文本和图标的颜色。 * @property {string} [lightScheme.info] - The info color used in light mode. - 亮色模式下使用的信息颜色。 * @property {string} [lightScheme.onInfo] - The color used for text and icons on top of the info color. - 用于信息颜色上的文本和图标的颜色。 * @property {string} [lightScheme.infoContainer] - The info container color used in light mode. - 亮色模式下使用的信息容器颜色。 * @property {string} [lightScheme.onInfoContainer] - The color used for text and icons on top of the info container color. - 用于信息容器颜色上的文本和图标的颜色。 * @property {string} [lightScheme.warning] - The warning color used in light mode. - 亮色模式下使用的警告颜色。 * @property {string} [lightScheme.onWarning] - The color used for text and icons on top of the warning color. - 用于警告颜色上的文本和图标的颜色。 * @property {string} [lightScheme.warningContainer] - The warning container color used in light mode. - 亮色模式下使用的警告容器颜色。 * @property {string} [lightScheme.onWarningContainer] - The color used for text and icons on top of the warning container color. - 用于警告容器颜色上的文本和图标的颜色。 * @property {string} [lightScheme.success] - The success color used in light mode. - 亮色模式下使用的成功颜色。 * @property {string} [lightScheme.onSuccess] - The color used for text and icons on top of the success color. - 用于成功颜色上的文本和图标的颜色。 * @property {string} [lightScheme.successContainer] - The success container color used in light mode. - 亮色模式下使用的成功容器颜色。 * @property {string} [lightScheme.onSuccessContainer] - The color used for text and icons on top of the success container color. - 用于成功容器颜色上的文本和图标的颜色。 * @property {string} lightScheme.background - The background color used in light mode. - 亮色模式下使用的背景颜色。 * @property {string} lightScheme.onBackground - The color used for text and icons on top of the background color. - 用于背景颜色上的文本和图标的颜色。 * @property {string} lightScheme.surface - The surface color used in light mode. - 亮色模式下使用的表面颜色。 * @property {string} lightScheme.onSurface - The color used for text and icons on top of the surface color. - 用于表面颜色上的文本和图标的颜色。 * @property {string} lightScheme.surfaceVariant - The surface variant color used in light mode. - 亮色模式下使用的表面变体颜色。 * @property {string} lightScheme.onSurfaceVariant - The color used for text and icons on top of the surface variant color. - 用于表面变体颜色上的文本和图标的颜色。 * @property {string} lightScheme.surfaceContainerLowest - The lowest surface container color used in light mode. - 亮色模式下使用的最低表面容器颜色。 * @property {string} lightScheme.surfaceContainerLow - The low surface container color used in light mode. - 亮色模式下使用的低表面容器颜色。 * @property {string} lightScheme.surfaceContainer - The surface container color used in light mode. - 亮色模式下使用的表面容器颜色。 * @property {string} lightScheme.surfaceContainerHigh - The high surface container color used in light mode. - 亮色模式下使用的高表面容器颜色。 * @property {string} lightScheme.surfaceContainerHighest - The highest surface container color used in light mode. - 亮色模式下使用的最高表面容器颜色。 * @property {string} lightScheme.inverseSurface - The inverse surface color used in light mode. - 亮色模式下使用的反色表面颜色。 * @property {string} lightScheme.inverseOnSurface - The color used for text and icons on top of the inverse surface color. - 用于反色表面颜色上的文本和图标的颜色。 * @property {string} lightScheme.inversePrimary - The inverse primary color used in light mode. - 亮色模式下使用的反色主色。 * @property {string} lightScheme.surfaceTint - The surface tint color used in light mode. - 亮色模式下使用的表面色调。 * @property {string} lightScheme.outline - The outline color used in light mode. - 亮色模式下使用的轮廓颜色。 * @property {string} lightScheme.outlineVariant - The outline variant color used in light mode. - 亮色模式下使用的轮廓变体颜色。 * @property {string} lightScheme.shadow - The shadow color used in light mode. - 亮色模式下使用的阴影颜色。 * @property {MD3ColorSchemeTokens} darkScheme - The color scheme for dark mode. - 暗色模式的颜色方案。 * The dark scheme defines the colors used when the theme is in dark mode. - 暗色模式定义了主题在暗色模式下使用的颜色。 * @property {string} darkScheme.primary - The primary color used in dark mode. - 暗色模式下使用的主色。 * @property {string} darkScheme.onPrimary - The color used for text and icons on top of the primary color. - 用于主色上的文本和图标的颜色。 * @property {string} darkScheme.primaryContainer - The primary container color used in dark mode. - 暗色模式下使用的主容器颜色。 * @property {string} darkScheme.onPrimaryContainer - The color used for text and icons on top of the primary container color. - 用于主容器颜色上的文本和图标的颜色。 * @property {string} darkScheme.secondary - The secondary color used in dark mode. - 暗色模式下使用的次要颜色。 * @property {string} darkScheme.onSecondary - The color used for text and icons on top of the secondary color. - 用于次要颜色上的文本和图标的颜色。 * @property {string} darkScheme.secondaryContainer - The secondary container color used in dark mode. - 暗色模式下使用的次要容器颜色。 * @property {string} darkScheme.onSecondaryContainer - The color used for text and icons on top of the secondary container color. - 用于次要容器颜色上的文本和图标的颜色。 * @property {string} darkScheme.tertiary - The tertiary color used in dark mode. - 暗色模式下使用的第三色。 * @property {string} darkScheme.onTertiary - The color used for text and icons on top of the tertiary color. - 用于第三色上的文本和图标的颜色。 * @property {string} darkScheme.tertiaryContainer - The tertiary container color used in dark mode. - 暗色模式下使用的第三色容器颜色。 * @property {string} darkScheme.onTertiaryContainer - The color used for text and icons on top of the tertiary container color. - 用于第三色容器颜色上的文本和图标的颜色。 * @property {string} darkScheme.error - The error color used in dark mode. - 暗色模式下使用的错误颜色。 * @property {string} darkScheme.onError - The color used for text and icons on top of the error color. - 用于错误颜色上的文本和图标的颜色。 * @property {string} darkScheme.errorContainer - The error container color used in dark mode. - 暗色模式下使用的错误容器颜色。 * @property {string} darkScheme.onErrorContainer - The color used for text and icons on top of the error container color. - 用于错误容器颜色上的文本和图标的颜色。 * @property {string} [darkScheme.info] - The info color used in dark mode. - 暗色模式下使用的信息颜色。 * @property {string} [darkScheme.onInfo] - The color used for text and icons on top of the info color. - 用于信息颜色上的文本和图标的颜色。 * @property {string} [darkScheme.infoContainer] - The info container color used in dark mode. - 暗色模式下使用的信息容器颜色。 * @property {string} [darkScheme.onInfoContainer] - The color used for text and icons on top of the info container color. - 用于信息容器颜色上的文本和图标的颜色。 * @property {string} [darkScheme.warning] - The warning color used in dark mode. - 暗色模式下使用的警告颜色。 * @property {string} [darkScheme.onWarning] - The color used for text and icons on top of the warning color. - 用于警告颜色上的文本和图标的颜色。 * @property {string} [darkScheme.warningContainer] - The warning container color used in dark mode. - 暗色模式下使用的警告容器颜色。 * @property {string} [darkScheme.onWarningContainer] - The color used for text and icons on top of the warning container color. - 用于警告容器颜色上的文本和图标的颜色。 * @property {string} [darkScheme.success] - The success color used in dark mode. - 暗色模式下使用的成功颜色。 * @property {string} [darkScheme.onSuccess] - The color used for text and icons on top of the success color. - 用于成功颜色上的文本和图标的颜色。 * @property {string} [darkScheme.successContainer] - The success container color used in dark mode. - 暗色模式下使用的成功容器颜色。 * @property {string} [darkScheme.onSuccessContainer] - The color used for text and icons on top of the success container color. - 用于成功容器颜色上的文本和图标的颜色。 * @property {string} darkScheme.background - The background color used in dark mode. - 暗色模式下使用的背景颜色。 * @property {string} darkScheme.onBackground - The color used for text and icons on top of the background color. - 用于背景颜色上的文本和图标的颜色。 * @property {string} darkScheme.surface - The surface color used in dark mode. - 暗色模式下使用的表面颜色。 * @property {string} darkScheme.onSurface - The color used for text and icons on top of the surface color. - 用于表面颜色上的文本和图标的颜色。 * @property {string} darkScheme.surfaceVariant - The surface variant color used in dark mode. - 暗色模式下使用的表面变体颜色。 * @property {string} darkScheme.onSurfaceVariant - The color used for text and icons on top of the surface variant color. - 用于表面变体颜色上的文本和图标的颜色。 * @property {string} darkScheme.surfaceContainerLowest - The lowest surface container color used in dark mode. - 暗色模式下使用的最低表面容器颜色。 * @property {string} darkScheme.surfaceContainerLow - The low surface container color used in dark mode. - 暗色模式下使用的低表面容器颜色。 * @property {string} darkScheme.surfaceContainer - The surface container color used in dark mode. - 暗色模式下使用的表面容器颜色。 * @property {string} darkScheme.surfaceContainerHigh - The high surface container color used in dark mode. - 暗色模式下使用的高表面容器颜色。 * @property {string} darkScheme.surfaceContainerHighest - The highest surface container color used in dark mode. - 暗色模式下使用的最高表面容器颜色。 * @property {string} darkScheme.inverseSurface - The inverse surface color used in dark mode. - 暗色模式下使用的反色表面颜色。 * @property {string} darkScheme.inverseOnSurface - The color used for text and icons on top of the inverse surface color. - 用于反色表面颜色上的文本和图标的颜色。 * @property {string} darkScheme.inversePrimary - The inverse primary color used in dark mode. - 暗色模式下使用的反色主色。 * @property {string} darkScheme.surfaceTint - The surface tint color used in dark mode. - 暗色模式下使用的表面色调。 * @property {string} darkScheme.outline - The outline color used in dark mode. - 暗色模式下使用的轮廓颜色。 * @property {string} darkScheme.outlineVariant - The outline variant color used in dark mode. - 暗色模式下使用的轮廓变体颜色。 * @property {string} darkScheme.shadow - The shadow color used in dark mode. - 暗色模式下使用的阴影颜色。 */ export function generateTheme({ primary, secondary, tertiary, error, info, warning, success, neutral, neutralVariant, }: { primary: string secondary: string tertiary: string error: string info: string warning: string success: string neutral: string neutralVariant: string }): AppTheme { const primaryTonal = TonalPalette.fromInt(argbFromHex(primary)); const secondaryTonal = TonalPalette.fromInt(argbFromHex(secondary)); const tertiaryTonal = TonalPalette.fromInt(argbFromHex(tertiary)); const errorTonal = TonalPalette.fromInt(argbFromHex(error)); const infoTonal = TonalPalette.fromInt(argbFromHex(info)); const warningTonal = TonalPalette.fromInt(argbFromHex(warning)); const successTonal = TonalPalette.fromInt(argbFromHex(success)); const neutralTonal = TonalPalette.fromInt(argbFromHex(neutral)); const neutralVariantTonal = TonalPalette.fromInt(argbFromHex(neutralVariant)); const themeColors: { primary: MD3Tones secondary: MD3Tones tertiary: MD3Tones error: MD3Tones info: MD3Tones warning: MD3Tones success: MD3Tones neutral: MD3NeutralTones neutralVariant: MD3Tones } = { primary: generateTonalColors(primaryTonal), secondary: generateTonalColors(secondaryTonal), tertiary: generateTonalColors(tertiaryTonal), error: generateTonalColors(errorTonal), info: generateTonalColors(infoTonal), warning: generateTonalColors(warningTonal), success: generateTonalColors(successTonal), neutral: generateNeutralColors(neutralTonal), neutralVariant: generateTonalColors(neutralVariantTonal), }; const palette: MD3Palettes = { ...themeColors, common: { white: '#fff', black: '#000', }, }; const lightScheme: MD3ColorSchemeTokens = { // primary primary: palette.primary[40], onPrimary: palette.primary[100], primaryContainer: palette.primary[90], onPrimaryContainer: palette.primary[10], // secondary secondary: palette.secondary[40], onSecondary: palette.secondary[100], secondaryContainer: palette.secondary[90], onSecondaryContainer: palette.secondary[10], // tertiary tertiary: palette.tertiary[40], onTertiary: palette.tertiary[100], tertiaryContainer: palette.tertiary[90], onTertiaryContainer: palette.tertiary[10], // error error: palette.error[40], onError: palette.error[100], errorContainer: palette.error[90], onErrorContainer: palette.error[10], // info info: palette.info[40], onInfo: palette.info[100], infoContainer: palette.info[90], onInfoContainer: palette.info[10], // warning warning: palette.warning[40], onWarning: palette.warning[100], warningContainer: palette.warning[90], onWarningContainer: palette.warning[10], // success success: palette.success[40], onSuccess: palette.success[100], successContainer: palette.success[90], onSuccessContainer: palette.success[10], // surface surface: palette.neutral[98], onSurface: palette.neutral[10], surfaceVariant: palette.neutralVariant[90], onSurfaceVariant: palette.neutralVariant[30], surfaceContainerLowest: palette.neutral[100], surfaceContainerLow: palette.neutral[96], surfaceContainer: palette.neutral[94], surfaceContainerHigh: palette.neutral[92], surfaceContainerHighest: palette.neutral[90], surfaceTint: palette.primary[40], // outline outline: palette.neutralVariant[50], outlineVariant: palette.neutralVariant[80], shadow: palette.neutral[0], // background background: palette.neutral[98], onBackground: palette.neutral[10], // inverse inversePrimary: palette.primary[80], inverseSurface: palette.neutral[20], inverseOnSurface: palette.neutral[95], }; const darkScheme: MD3ColorSchemeTokens = { // primary primary: palette.primary[80], onPrimary: palette.primary[20], primaryContainer: palette.primary[30], onPrimaryContainer: palette.primary[90], // secondary secondary: palette.secondary[80], onSecondary: palette.secondary[20], secondaryContainer: palette.secondary[30], onSecondaryContainer: palette.secondary[90], // tertiary tertiary: palette.tertiary[80], onTertiary: palette.tertiary[20], tertiaryContainer: palette.tertiary[30], onTertiaryContainer: palette.tertiary[90], // error error: palette.error[80], onError: palette.error[20], errorContainer: palette.error[30], onErrorContainer: palette.error[90], // info info: palette.info[80], onInfo: palette.info[20], infoContainer: palette.info[30], onInfoContainer: palette.info[90], // warning warning: palette.warning[80], onWarning: palette.warning[20], warningContainer: palette.warning[30], onWarningContainer: palette.warning[90], // success success: palette.success[80], onSuccess: palette.success[20], successContainer: palette.success[30], onSuccessContainer: palette.success[90], // surface surface: palette.neutral[6], onSurface: palette.neutral[90], surfaceVariant: palette.neutralVariant[30], onSurfaceVariant: palette.neutralVariant[80], surfaceContainerLowest: palette.neutral[4], surfaceContainerLow: palette.neutral[10], surfaceContainer: palette.neutral[12], surfaceContainerHigh: palette.neutral[17], surfaceContainerHighest: palette.neutral[24], surfaceTint: palette.primary[80], // outline outline: palette.neutralVariant[60], outlineVariant: palette.neutralVariant[30], shadow: palette.neutral[0], // background background: palette.neutral[6], onBackground: palette.neutral[90], // inverse inversePrimary: palette.primary[40], inverseSurface: palette.neutral[90], inverseOnSurface: palette.neutral[20], }; return { palette, lightScheme, darkScheme, }; } function generateTonalColors(tonal: TonalPalette): MD3Tones { const tones: (keyof MD3Tones)[] = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 95, 99, 100]; const result: MD3NeutralTones = {} as MD3NeutralTones; tones.forEach((tone) => { result[tone] = hexFromArgb(tonal.tone(tone)); }); return result; } function generateNeutralColors(tonal: TonalPalette): MD3NeutralTones { const tones: (keyof MD3NeutralTones)[] = [0, 4, 6, 10, 12, 17, 20, 22, 24, 30, 40, 50, 60, 70, 80, 90, 92, 94, 95, 96, 98, 99, 100]; const result: MD3NeutralTones = {} as MD3NeutralTones; tones.forEach((tone) => { result[tone] = hexFromArgb(tonal.tone(tone)); }); return result; }