Skip to content

Commit 45e4e8a

Browse files
committed
feat(theming-material): use Hct as type of colors
1 parent c5dda15 commit 45e4e8a

5 files changed

Lines changed: 68 additions & 21 deletions

File tree

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { forwardRef, Injectable } from '@angular/core';
2+
import { Hct, hexFromArgb } from '@material/material-color-utilities';
3+
4+
/**
5+
* Service responsible for formatting HCT color values into strings, which will
6+
* be used as theme token values.
7+
* @remarks This is an abstract service, with a default implementation
8+
* `HexStringTextHctFormatter`.
9+
*/
10+
@Injectable({
11+
providedIn: 'root',
12+
useExisting: forwardRef(() => HexStringTextHctFormatter),
13+
})
14+
export abstract class HctFormatter {
15+
abstract format(value: Hct): string;
16+
}
17+
18+
/**
19+
* Implementation of `HctFormatter` that formats HCT color values into hex
20+
* strings such as `#ffffff`.
21+
*/
22+
@Injectable({
23+
providedIn: 'root',
24+
})
25+
export class HexStringTextHctFormatter implements HctFormatter {
26+
format(value: Hct): string {
27+
return hexFromArgb(value.toInt());
28+
}
29+
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
export * from './hct-formatter.service';
12
export * from './image-seed-color-extractor.service';
23
export * from './scheme';
3-
export * from './scheme-extended';
4+
export * from './scheme-static-color';
45
export * from './typescale';
56
export * from './typescale-standard';

packages/theming-material/src/scheme-static-color.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,40 @@
1+
import { inject } from '@angular/core';
12
import {
23
ThemeBuilder,
34
ThemeBuilderContext,
45
ThemeTokens,
56
} from '@angularity/theming';
6-
import {
7-
argbFromHex,
8-
hexFromArgb,
9-
TonalPalette,
10-
} from '@material/material-color-utilities';
7+
import { Hct, TonalPalette } from '@material/material-color-utilities';
118

9+
import { HctFormatter } from './hct-formatter.service';
1210
import { SchemeMode } from './scheme';
1311

1412
export interface SchemeStaticColorBuilderConfig {
1513
name: string;
16-
source: string;
14+
source: Hct;
1715
mode: SchemeMode;
1816
}
1917

2018
export class SchemeStaticColorBuilder
2119
implements ThemeBuilder<SchemeStaticColorBuilderConfig>
2220
{
21+
protected hctFormatter = inject(HctFormatter);
22+
2323
build(
2424
context: ThemeBuilderContext<SchemeStaticColorBuilderConfig>,
2525
): ThemeTokens {
2626
const { name, config } = context;
27-
const palette = TonalPalette.fromInt(argbFromHex(config.source));
27+
const palette = TonalPalette.fromHct(config.source);
2828
const tones = this.getStaticColorTones(config.mode);
29+
const format = (argb: number) =>
30+
this.hctFormatter.format(Hct.fromInt(argb));
2931
return {
30-
[`${name}-${config.name}`]: hexFromArgb(palette.tone(tones.color)),
31-
[`${name}-on-${config.name}`]: hexFromArgb(palette.tone(tones.onColor)),
32-
[`${name}-${config.name}-container`]: hexFromArgb(
32+
[`${name}-${config.name}`]: format(palette.tone(tones.color)),
33+
[`${name}-on-${config.name}`]: format(palette.tone(tones.onColor)),
34+
[`${name}-${config.name}-container`]: format(
3335
palette.tone(tones.colorContainer),
3436
),
35-
[`${name}-on-${config.name}-container`]: hexFromArgb(
37+
[`${name}-on-${config.name}-container`]: format(
3638
palette.tone(tones.onColorContainer),
3739
),
3840
};

packages/theming-material/src/scheme.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { TestBed } from '@angular/core/testing';
44
import { provideTheme, ThemeTokenRegistry } from '@angularity/theming';
5-
import { SchemeVibrant } from '@material/material-color-utilities';
5+
import { Hct, SchemeVibrant } from '@material/material-color-utilities';
66
import { withThemeBuilder } from 'packages/theming/src/builder-composition';
77

88
import { provide } from '../../core/src/provide';
@@ -16,7 +16,7 @@ describe('SchemeBuilder', () => {
1616
provideTheme(
1717
withThemeBuilder('scheme', SchemeBuilder, {
1818
type: SchemeVibrant,
19-
source: '#33bdff',
19+
source: Hct.fromInt(0x33bdff),
2020
mode: SchemeMode.Light,
2121
contrast: SchemeContrastLevel.Standard,
2222
}),

packages/theming-material/src/scheme.ts

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
import { Injectable } from '@angular/core';
1+
import { inject, Injectable } from '@angular/core';
22
import {
33
ThemeBuilder,
44
ThemeBuilderContext,
55
ThemeTokens,
66
} from '@angularity/theming';
77
import {
8-
argbFromHex,
98
DynamicColor,
109
DynamicScheme,
1110
Hct,
12-
hexFromArgb,
1311
MaterialDynamicColors,
1412
} from '@material/material-color-utilities';
1513

14+
import { HctFormatter } from './hct-formatter.service';
15+
1616
/**
1717
* Mode for Material color schemes.
1818
* @see `SchemeBuilder`
@@ -23,7 +23,8 @@ export enum SchemeMode {
2323
}
2424

2525
/**
26-
* Common contrast level values for Material color schemes.
26+
* Common contrast level values for Material color schemes. `Standard` should
27+
* fit for most use cases.
2728
* @see `SchemeBuilder`
2829
*/
2930
export enum SchemeContrastLevel {
@@ -69,8 +70,18 @@ export interface SchemeBuilderConfig {
6970
* The source/seed color to use for creating the color scheme. The generated
7071
* color scheme may deviate from this color at some extent, depending on the
7172
* chrome of the source color and the algorithm used by the `SchemeType`.
73+
*
74+
* @remarks `Hct` is the color representation from `material-color-utilities`,
75+
* which consists of hue, chroma, and tone.
76+
*
77+
* @example
78+
* ```ts
79+
* import { Hct, argbFromHex } from '@material/material-color-utilities';
80+
* Hct.fromInt(0xc2e7ff)
81+
* Hct.fromInt(argbFromHex("#c2e7ff"))
82+
* ```
7283
*/
73-
source: string;
84+
source: Hct;
7485

7586
/**
7687
* The mode of the color scheme. Light or Dark.
@@ -91,21 +102,25 @@ export interface SchemeBuilderConfig {
91102
*/
92103
@Injectable({ providedIn: 'root' })
93104
export class SchemeBuilder implements ThemeBuilder<SchemeBuilderConfig> {
105+
protected hctFormatter = inject(HctFormatter);
106+
94107
build(context: ThemeBuilderContext<SchemeBuilderConfig>): ThemeTokens {
95108
const scheme = this.getScheme(context.config);
96109
const tokens: ThemeTokens = {};
97110
for (const [k, v] of Object.entries(MaterialDynamicColors)) {
98111
if (!(v instanceof DynamicColor)) continue;
99112
const name = k.replace(/([a-z])([A-Z])/gu, '$1-$2').toLowerCase();
113+
const color = v.getHct(scheme);
100114
const token = `${context.name}-${name}`;
101-
tokens[token] = hexFromArgb(v.getArgb(scheme));
115+
const value = this.hctFormatter.format(color);
116+
tokens[token] = value;
102117
}
103118
return tokens;
104119
}
105120

106121
protected getScheme(config: SchemeBuilderConfig): DynamicScheme {
107122
return new config.type(
108-
Hct.fromInt(argbFromHex(config.source)),
123+
config.source,
109124
config.mode === SchemeMode.Dark,
110125
config.contrast,
111126
);

0 commit comments

Comments
 (0)