@@ -6,43 +6,89 @@ import {
66} from '@angularity/theming' ;
77import {
88 argbFromHex ,
9- CorePalette ,
109 DynamicColor ,
1110 DynamicScheme ,
11+ Hct ,
1212 hexFromArgb ,
1313 MaterialDynamicColors ,
1414} from '@material/material-color-utilities' ;
1515
1616/**
17- * Copy of the internal enum `Variant` from `@material/material-color-utilities`.
17+ * Mode for Material color schemes.
18+ * @see `SchemeBuilder`
1819 */
19- export enum SchemeVariant {
20- /* eslint-disable @typescript-eslint/naming-convention */
21- MONOCHROME = 0 ,
22- NEUTRAL = 1 ,
23- TONAL_SPOT = 2 ,
24- VIBRANT = 3 ,
25- EXPRESSIVE = 4 ,
26- FIDELITY = 5 ,
27- CONTENT = 6 ,
28- RAINBOW = 7 ,
29- FRUIT_SALAD = 8 ,
30- /* eslint-enable @typescript-eslint/naming-convention */
31- }
32-
3320export enum SchemeMode {
3421 Light = 'Light' ,
3522 Dark = 'Dark' ,
3623}
3724
25+ /**
26+ * Common contrast level values for Material color schemes.
27+ * @see `SchemeBuilder`
28+ */
29+ export enum SchemeContrastLevel {
30+ Reduced = - 1.0 ,
31+ Standard = 0.0 ,
32+ Medium = 0.5 ,
33+ High = 1.0 ,
34+ }
35+
36+ /**
37+ * Constructor of `DynamicScheme` from `material-color-utilities`.
38+ *
39+ * Available values include:
40+ * - `SchemeTonalSpot`: classic Material Design 3 colors
41+ * - `SchemeVibrant`: more vibrant colors
42+ * - `SchemeMonochrome`: grayscale colors
43+ * - `SchemeNeutral`: colors that are nearly grayscale
44+ * - `SchemeFidelity`: match the source color as closely as possible
45+ * - etc.
46+ *
47+ * @see https://github.com/material-foundation/material-color-utilities/tree/main/typescript/scheme for all available scheme types
48+ *
49+ * @example
50+ * ```ts
51+ * import { SchemeTonalSpot } from '@material/material-color-utilities';
52+ * const type: SchemeType = SchemeTonalSpot;
53+ * ```
54+ */
55+ export interface SchemeType {
56+ new ( source : Hct , isDark : boolean , contrast : number ) : DynamicScheme ;
57+ }
58+
59+ /**
60+ * Configuration for `SchemeBuilder`.
61+ */
3862export interface SchemeBuilderConfig {
39- primary : string ;
40- secondary ?: string ;
41- tertiary ?: string ;
42- variant : SchemeVariant ;
63+ /**
64+ * The type of color scheme to generate. See `SchemeType` for details.
65+ */
66+ type : SchemeType ;
67+
68+ /**
69+ * The source/seed color to use for creating the color scheme. The generated
70+ * color scheme may deviate from this color at some extent, depending on the
71+ * chrome of the source color and the algorithm used by the `SchemeType`.
72+ */
73+ source : string ;
74+
75+ /**
76+ * The mode of the color scheme. Light or Dark.
77+ */
4378 mode : SchemeMode ;
79+
80+ /**
81+ * The contrast level of the color scheme. See `SchemeContrastLevel` for
82+ * common values, or use a number between -1 to 1 for custom values, where
83+ * -1 is the lowest contrast and 1 is the highest.
84+ */
85+ contrast : SchemeContrastLevel | number ;
4486}
4587
88+ /**
89+ * Implementation of `ThemeBuilder` that generates hex color tokens for all
90+ * color roles under Material Design 3 color schemes.
91+ */
4692@Injectable ( { providedIn : 'root' } )
4793export class SchemeBuilder implements ThemeBuilder < SchemeBuilderConfig > {
4894 build ( context : ThemeBuilderContext < SchemeBuilderConfig > ) : ThemeTokens {
@@ -57,29 +103,11 @@ export class SchemeBuilder implements ThemeBuilder<SchemeBuilderConfig> {
57103 return tokens ;
58104 }
59105
60- getScheme ( config : SchemeBuilderConfig ) : DynamicScheme {
61- const palette = this . getCorePalette ( config ) ;
62- const scheme = new DynamicScheme ( {
63- sourceColorArgb : argbFromHex ( config . primary ) ,
64- variant : config . variant as any ,
65- isDark : config . mode === SchemeMode . Dark ,
66- contrastLevel : 0.0 ,
67- primaryPalette : palette . a1 ,
68- secondaryPalette : palette . a2 ,
69- tertiaryPalette : palette . a3 ,
70- neutralPalette : palette . n1 ,
71- neutralVariantPalette : palette . n2 ,
72- } ) ;
73- return scheme ;
74- }
75-
76- getCorePalette ( config : SchemeBuilderConfig ) : CorePalette {
77- const read = ( v : string ) => argbFromHex ( v ) ;
78- const readOpt = ( v : string | undefined ) => ( v ? read ( v ) : undefined ) ;
79- return CorePalette . fromColors ( {
80- primary : read ( config . primary ) ,
81- secondary : readOpt ( config . secondary ) ,
82- tertiary : readOpt ( config . tertiary ) ,
83- } ) ;
106+ protected getScheme ( config : SchemeBuilderConfig ) : DynamicScheme {
107+ return new config . type (
108+ Hct . fromInt ( argbFromHex ( config . source ) ) ,
109+ config . mode === SchemeMode . Dark ,
110+ config . contrast ,
111+ ) ;
84112 }
85113}
0 commit comments