363 lines
23 KiB
TypeScript
363 lines
23 KiB
TypeScript
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;
|
|
}
|