@udixio/theme 1.3.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -2
- package/dist/API.d.ts +7 -4
- package/dist/API.d.ts.map +1 -1
- package/dist/app.container.d.ts +1 -2
- package/dist/app.container.d.ts.map +1 -1
- package/dist/bin.cjs +1 -1
- package/dist/bin.js +1 -1
- package/dist/browser.cjs +23 -18
- package/dist/browser.js +34 -29
- package/dist/color/color.api.d.ts +16 -31
- package/dist/color/color.api.d.ts.map +1 -1
- package/dist/color/color.d.ts +100 -0
- package/dist/color/color.d.ts.map +1 -0
- package/dist/color/color.manager.d.ts +9 -18
- package/dist/color/color.manager.d.ts.map +1 -1
- package/dist/color/color.utils.d.ts +14 -3
- package/dist/color/color.utils.d.ts.map +1 -1
- package/dist/color/default-color.d.ts +5 -1
- package/dist/color/default-color.d.ts.map +1 -1
- package/dist/color/index.d.ts +1 -1
- package/dist/color/index.d.ts.map +1 -1
- package/dist/config/config.interface.d.ts +4 -4
- package/dist/config/config.interface.d.ts.map +1 -1
- package/dist/context/context.d.ts +41 -0
- package/dist/context/context.d.ts.map +1 -0
- package/dist/context/context.module.d.ts +3 -0
- package/dist/context/context.module.d.ts.map +1 -0
- package/dist/context/index.d.ts +3 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/font.plugin-5Xpo-ntw.js +228 -0
- package/dist/font.plugin-FPU_gL1Y.cjs +227 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/{load-from-path-Bo1kCfh9.js → load-from-path-CBnO8ESw.js} +1 -1
- package/dist/{load-from-path-DoZnR1-p.cjs → load-from-path-kuofMGN3.cjs} +2 -2
- package/dist/loader/loader.d.ts +1 -1
- package/dist/loader/loader.d.ts.map +1 -1
- package/dist/loader-BzsrGBu-.cjs +3905 -0
- package/dist/loader-CoayTlSl.js +3906 -0
- package/dist/material-color-utilities/dynamic_color.d.ts +0 -22
- package/dist/material-color-utilities/dynamic_color.d.ts.map +1 -1
- package/dist/material-color-utilities/toneDeltaPair.d.ts +8 -8
- package/dist/material-color-utilities/toneDeltaPair.d.ts.map +1 -1
- package/dist/node.cjs +24 -19
- package/dist/node.js +36 -31
- package/dist/palette/index.d.ts +4 -0
- package/dist/palette/index.d.ts.map +1 -0
- package/dist/palette/palette.api.d.ts +13 -0
- package/dist/palette/palette.api.d.ts.map +1 -0
- package/dist/palette/palette.d.ts +33 -0
- package/dist/palette/palette.d.ts.map +1 -0
- package/dist/palette/palette.manager.d.ts +20 -0
- package/dist/palette/palette.manager.d.ts.map +1 -0
- package/dist/palette/palette.module.d.ts +3 -0
- package/dist/palette/palette.module.d.ts.map +1 -0
- package/dist/plugins/font/font.plugin.d.ts +1 -1
- package/dist/plugins/font/font.plugin.d.ts.map +1 -1
- package/dist/variant/index.d.ts +3 -0
- package/dist/variant/index.d.ts.map +1 -0
- package/dist/variant/variant.d.ts +31 -0
- package/dist/variant/variant.d.ts.map +1 -0
- package/dist/variant/variants/expressive.variant.d.ts +2 -0
- package/dist/variant/variants/expressive.variant.d.ts.map +1 -0
- package/dist/{theme → variant}/variants/index.d.ts +1 -1
- package/dist/variant/variants/index.d.ts.map +1 -0
- package/dist/variant/variants/neutral.variant.d.ts.map +1 -0
- package/dist/variant/variants/tonal-spot.variant.d.ts.map +1 -0
- package/dist/variant/variants/udixio.variant.d.ts +3 -0
- package/dist/variant/variants/udixio.variant.d.ts.map +1 -0
- package/dist/variant/variants/vibrant.variant.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/API.ts +12 -5
- package/src/app.container.ts +22 -11
- package/src/bootstrap.ts +1 -1
- package/src/color/color.api.ts +189 -47
- package/src/color/color.manager.ts +34 -189
- package/src/color/color.ts +295 -0
- package/src/color/color.utils.ts +48 -3
- package/src/color/default-color.ts +390 -425
- package/src/color/index.ts +1 -1
- package/src/config/config.interface.ts +5 -4
- package/src/context/context.module.ts +7 -0
- package/src/context/context.ts +169 -0
- package/src/context/index.ts +2 -0
- package/src/index.ts +6 -4
- package/src/loader/loader.ts +11 -24
- package/src/material-color-utilities/dynamic_color.ts +25 -34
- package/src/material-color-utilities/toneDeltaPair.ts +44 -41
- package/src/palette/index.ts +3 -0
- package/src/palette/palette.api.ts +43 -0
- package/src/palette/palette.manager.ts +74 -0
- package/src/palette/palette.module.ts +9 -0
- package/src/palette/palette.ts +206 -0
- package/src/plugins/font/font.plugin.ts +1 -1
- package/src/variant/index.ts +2 -0
- package/src/variant/variant.ts +84 -0
- package/src/{theme → variant}/variants/expressive.variant.ts +33 -29
- package/src/{theme → variant}/variants/index.ts +2 -2
- package/src/variant/variants/neutral.variant.ts +47 -0
- package/src/variant/variants/tonal-spot.variant.ts +37 -0
- package/src/variant/variants/udixio.variant.ts +846 -0
- package/src/{theme → variant}/variants/vibrant.variant.ts +23 -22
- package/dist/color/configurable-color.d.ts +0 -31
- package/dist/color/configurable-color.d.ts.map +0 -1
- package/dist/define-config-BasMdCqD.js +0 -430
- package/dist/define-config-CKSsLMnc.cjs +0 -429
- package/dist/loader-C8_TyOuS.js +0 -2698
- package/dist/loader-R7hccp8_.cjs +0 -2697
- package/dist/theme/index.d.ts +0 -8
- package/dist/theme/index.d.ts.map +0 -1
- package/dist/theme/scheme.d.ts +0 -20
- package/dist/theme/scheme.d.ts.map +0 -1
- package/dist/theme/scheme.manager.d.ts +0 -31
- package/dist/theme/scheme.manager.d.ts.map +0 -1
- package/dist/theme/theme.api.d.ts +0 -24
- package/dist/theme/theme.api.d.ts.map +0 -1
- package/dist/theme/theme.module.d.ts +0 -3
- package/dist/theme/theme.module.d.ts.map +0 -1
- package/dist/theme/variant.d.ts +0 -36
- package/dist/theme/variant.d.ts.map +0 -1
- package/dist/theme/variant.manager.d.ts +0 -14
- package/dist/theme/variant.manager.d.ts.map +0 -1
- package/dist/theme/variants/expressive.variant.d.ts +0 -3
- package/dist/theme/variants/expressive.variant.d.ts.map +0 -1
- package/dist/theme/variants/fidelity.variant.d.ts +0 -3
- package/dist/theme/variants/fidelity.variant.d.ts.map +0 -1
- package/dist/theme/variants/index.d.ts.map +0 -1
- package/dist/theme/variants/neutral.variant.d.ts.map +0 -1
- package/dist/theme/variants/tonal-spot.variant.d.ts.map +0 -1
- package/dist/theme/variants/vibrant.variant.d.ts.map +0 -1
- package/src/color/configurable-color.ts +0 -67
- package/src/theme/index.ts +0 -7
- package/src/theme/scheme.manager.ts +0 -100
- package/src/theme/scheme.ts +0 -66
- package/src/theme/theme.api.ts +0 -82
- package/src/theme/theme.module.ts +0 -11
- package/src/theme/variant.manager.ts +0 -58
- package/src/theme/variant.ts +0 -53
- package/src/theme/variants/fidelity.variant.ts +0 -38
- package/src/theme/variants/neutral.variant.ts +0 -45
- package/src/theme/variants/tonal-spot.variant.ts +0 -35
- /package/dist/{theme → variant}/variants/neutral.variant.d.ts +0 -0
- /package/dist/{theme → variant}/variants/tonal-spot.variant.d.ts +0 -0
- /package/dist/{theme → variant}/variants/vibrant.variant.d.ts +0 -0
package/src/color/index.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { AddColorsOptions } from '../color';
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
import { PluginAbstract } from '../plugin';
|
|
4
|
+
import { Variant } from '../variant/variant';
|
|
5
|
+
import { PaletteCallback } from '../palette/palette';
|
|
4
6
|
|
|
5
7
|
export interface ConfigInterface {
|
|
6
8
|
sourceColor: string;
|
|
7
9
|
contrastLevel?: number;
|
|
8
10
|
isDark?: boolean;
|
|
9
11
|
variant?: Variant;
|
|
10
|
-
colors?: AddColorsOptions
|
|
11
|
-
|
|
12
|
-
palettes?: Record<string, string>;
|
|
12
|
+
colors?: AddColorsOptions;
|
|
13
|
+
palettes?: Record<string, PaletteCallback | string>;
|
|
13
14
|
plugins?: PluginAbstract<any, any>[];
|
|
14
15
|
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { argbFromHex } from '@material/material-color-utilities';
|
|
2
|
+
import { Hct } from '../material-color-utilities/htc';
|
|
3
|
+
import { Variant } from '../variant/variant';
|
|
4
|
+
|
|
5
|
+
export interface ContextOptions {
|
|
6
|
+
sourceColor: string | Hct;
|
|
7
|
+
contrastLevel: number;
|
|
8
|
+
isDark: boolean;
|
|
9
|
+
variant: Variant;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class Context {
|
|
13
|
+
private _options?: ContextOptions;
|
|
14
|
+
private _temOptions: ContextOptions | null = null;
|
|
15
|
+
private readonly updateCallbacks: Array<
|
|
16
|
+
(changed: (keyof Context)[]) => void
|
|
17
|
+
> = [];
|
|
18
|
+
|
|
19
|
+
constructor() {
|
|
20
|
+
this.onUpdate((changed) => {
|
|
21
|
+
if (changed.includes('variant')) {
|
|
22
|
+
this.variant.init(this);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Runs the provided callback with a proxied Context and records which Context
|
|
29
|
+
* properties (getters) were accessed during its execution.
|
|
30
|
+
*
|
|
31
|
+
* This helps determine dependencies of the callback on the Context.
|
|
32
|
+
*
|
|
33
|
+
* Example usage:
|
|
34
|
+
* const { result, dependencies } = Context.trackDependencies(ctx, (c) => cb(c));
|
|
35
|
+
*/
|
|
36
|
+
static trackDependencies<T>(
|
|
37
|
+
context: Context,
|
|
38
|
+
callback: (ctx: Context) => T,
|
|
39
|
+
): { result: T; dependencies: (keyof Context)[] } {
|
|
40
|
+
const dependencies = new Set<keyof Context>();
|
|
41
|
+
|
|
42
|
+
const isGetterOnContext = (prop: PropertyKey): boolean => {
|
|
43
|
+
if (typeof prop !== 'string') return false;
|
|
44
|
+
const desc = Object.getOwnPropertyDescriptor(Context.prototype, prop);
|
|
45
|
+
return !!desc && typeof desc.get === 'function';
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const proxy = new Proxy(context, {
|
|
49
|
+
get(target, prop, receiver) {
|
|
50
|
+
if (isGetterOnContext(prop)) {
|
|
51
|
+
dependencies.add(prop as keyof Context);
|
|
52
|
+
}
|
|
53
|
+
return Reflect.get(target, prop, receiver);
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const result = callback(proxy as unknown as Context);
|
|
58
|
+
return { result, dependencies: Array.from(dependencies) };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
set(options: ContextOptions) {
|
|
62
|
+
if (this._options) {
|
|
63
|
+
console.error(this._options);
|
|
64
|
+
throw new Error('Options already set');
|
|
65
|
+
}
|
|
66
|
+
if (typeof options.sourceColor === 'string') {
|
|
67
|
+
options.sourceColor = Hct.fromInt(argbFromHex(options.sourceColor));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const changed: (keyof Context)[] = [];
|
|
71
|
+
for (const key of Object.keys(options) as (keyof ContextOptions)[]) {
|
|
72
|
+
changed.push(key);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
this._options = options;
|
|
76
|
+
|
|
77
|
+
if (changed.length > 0) {
|
|
78
|
+
this.updateCallbacks.forEach((callback) => callback(changed));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
public update(args: Partial<ContextOptions>) {
|
|
83
|
+
const options = this._options;
|
|
84
|
+
if (!options) {
|
|
85
|
+
throw new Error('Options not found');
|
|
86
|
+
}
|
|
87
|
+
if (typeof args.sourceColor === 'string') {
|
|
88
|
+
args.sourceColor = Hct.fromInt(argbFromHex(args.sourceColor));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// compute changed keys
|
|
92
|
+
const changed: (keyof Context)[] = [];
|
|
93
|
+
for (const key of Object.keys(args) as (keyof ContextOptions)[]) {
|
|
94
|
+
if ((args as any)[key] !== (options as any)[key]) {
|
|
95
|
+
changed.push(key);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
this._options = {
|
|
100
|
+
...options,
|
|
101
|
+
...args,
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// notify listeners with changed keys (if any)
|
|
105
|
+
if (changed.length > 0) {
|
|
106
|
+
this.updateCallbacks.forEach((callback) => callback(changed));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
private getOptions(): ContextOptions {
|
|
111
|
+
let options;
|
|
112
|
+
if (this._temOptions) {
|
|
113
|
+
options = this._temOptions;
|
|
114
|
+
} else {
|
|
115
|
+
options = this._options;
|
|
116
|
+
}
|
|
117
|
+
if (!options) {
|
|
118
|
+
throw new Error('Options not found');
|
|
119
|
+
}
|
|
120
|
+
return options;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
set darkMode(isDark: boolean) {
|
|
124
|
+
this.update({ isDark });
|
|
125
|
+
}
|
|
126
|
+
get isDark() {
|
|
127
|
+
return this.getOptions().isDark;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
set contrastLevel(contrastLevel: number) {
|
|
131
|
+
this.update({ contrastLevel });
|
|
132
|
+
}
|
|
133
|
+
get contrastLevel() {
|
|
134
|
+
return this.getOptions().contrastLevel;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
set sourceColor(sourceColor: string) {
|
|
138
|
+
this.update({ sourceColor });
|
|
139
|
+
}
|
|
140
|
+
get sourceColor(): Hct {
|
|
141
|
+
let sourceColor = this.getOptions().sourceColor;
|
|
142
|
+
if (typeof sourceColor === 'string') {
|
|
143
|
+
sourceColor = Hct.fromInt(argbFromHex(sourceColor));
|
|
144
|
+
}
|
|
145
|
+
return sourceColor;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
set variant(variant: Variant) {
|
|
149
|
+
this.update({ variant });
|
|
150
|
+
}
|
|
151
|
+
get variant() {
|
|
152
|
+
return this.getOptions().variant;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
temp<T>(args: Partial<ContextOptions>, callback: () => T): T {
|
|
156
|
+
const previousOptions = this.getOptions();
|
|
157
|
+
this._temOptions = {
|
|
158
|
+
...previousOptions,
|
|
159
|
+
...args,
|
|
160
|
+
};
|
|
161
|
+
const result = callback();
|
|
162
|
+
this._temOptions = null;
|
|
163
|
+
return result;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
onUpdate(callback: (changed: (keyof Context)[]) => void): void {
|
|
167
|
+
this.updateCallbacks.push(callback);
|
|
168
|
+
}
|
|
169
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
export * from './API';
|
|
1
2
|
export * from './app.container';
|
|
2
3
|
export * from './app.module';
|
|
3
|
-
export * from './
|
|
4
|
+
export * from './bootstrap';
|
|
4
5
|
export * from './color';
|
|
6
|
+
export * from './config';
|
|
7
|
+
export * from './context';
|
|
5
8
|
export * from './loader';
|
|
6
|
-
export * from './bootstrap';
|
|
7
9
|
export * from './material-color-utilities';
|
|
10
|
+
export * from './palette';
|
|
8
11
|
export * from './plugin';
|
|
9
12
|
export * from './plugins';
|
|
10
|
-
export * from './
|
|
11
|
-
export * from './config';
|
|
13
|
+
export * from './variant';
|
package/src/loader/loader.ts
CHANGED
|
@@ -1,45 +1,29 @@
|
|
|
1
|
-
import { tonalSpotVariant } from '../theme';
|
|
2
|
-
import { defaultColors } from '../color';
|
|
3
1
|
import { bootstrap } from '../bootstrap';
|
|
4
|
-
import { registerModule } from '../app.container';
|
|
5
|
-
import { asValue } from 'awilix';
|
|
6
2
|
import { ConfigInterface } from '../config';
|
|
3
|
+
import { Variants } from '../variant/variants';
|
|
7
4
|
|
|
8
|
-
const
|
|
5
|
+
export const loader = async (config: ConfigInterface, load = true) => {
|
|
9
6
|
const api = bootstrap();
|
|
10
|
-
registerModule({
|
|
11
|
-
adapter: asValue(this),
|
|
12
|
-
});
|
|
13
|
-
return api;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export const loader = async (config: ConfigInterface) => {
|
|
17
|
-
const api = initializeApi();
|
|
18
7
|
|
|
19
8
|
const init = () => {
|
|
20
9
|
const {
|
|
21
10
|
sourceColor,
|
|
22
11
|
contrastLevel = 0,
|
|
23
12
|
isDark = false,
|
|
24
|
-
variant =
|
|
13
|
+
variant = Variants.TonalSpot,
|
|
25
14
|
palettes,
|
|
26
15
|
colors,
|
|
27
|
-
useDefaultColors = true,
|
|
28
16
|
plugins,
|
|
29
17
|
} = config;
|
|
30
|
-
|
|
18
|
+
|
|
19
|
+
api.context.set({
|
|
31
20
|
contrastLevel: contrastLevel,
|
|
32
21
|
isDark: isDark,
|
|
33
|
-
|
|
22
|
+
sourceColor,
|
|
34
23
|
variant: variant,
|
|
35
24
|
});
|
|
36
25
|
if (palettes) {
|
|
37
|
-
|
|
38
|
-
api.themes.addCustomPalette(key, value),
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
if (useDefaultColors) {
|
|
42
|
-
api.colors.addColors(defaultColors);
|
|
26
|
+
api.palettes.add(palettes);
|
|
43
27
|
}
|
|
44
28
|
if (colors) {
|
|
45
29
|
api.colors.addColors(colors);
|
|
@@ -53,7 +37,10 @@ export const loader = async (config: ConfigInterface) => {
|
|
|
53
37
|
};
|
|
54
38
|
|
|
55
39
|
init();
|
|
56
|
-
|
|
40
|
+
|
|
41
|
+
if (load) {
|
|
42
|
+
await api.load();
|
|
43
|
+
}
|
|
57
44
|
|
|
58
45
|
return api;
|
|
59
46
|
};
|
|
@@ -50,22 +50,22 @@ import { Hct } from './htc';
|
|
|
50
50
|
* constructed. When not provided or resolved as undefined, the tone is
|
|
51
51
|
* calculated based on other constraints.
|
|
52
52
|
*/
|
|
53
|
-
export interface FromPaletteOptions {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
53
|
+
// export interface FromPaletteOptions {
|
|
54
|
+
// name?: string;
|
|
55
|
+
// palette: (scheme: Scheme) => TonalPalette;
|
|
56
|
+
// tone?: (scheme: Scheme) => number;
|
|
57
|
+
// chromaMultiplier?: (scheme: Scheme) => number;
|
|
58
|
+
// isBackground?: boolean;
|
|
59
|
+
// background?: (scheme: Scheme) => DynamicColor | undefined;
|
|
60
|
+
// secondBackground?: (scheme: Scheme) => DynamicColor | undefined;
|
|
61
|
+
// contrastCurve?: (scheme: Scheme) => ContrastCurve | undefined;
|
|
62
|
+
// adjustTone?: (scheme: Scheme) => AdjustTone | undefined;
|
|
63
|
+
// }
|
|
64
64
|
|
|
65
|
-
export type AdjustTone = (args: {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}) => number;
|
|
65
|
+
// export type AdjustTone = (args: {
|
|
66
|
+
// scheme: Scheme;
|
|
67
|
+
// dynamicColor: DynamicColor;
|
|
68
|
+
// }) => number;
|
|
69
69
|
|
|
70
70
|
/**
|
|
71
71
|
* A color that adjusts itself based on UI state provided by DynamicScheme.
|
|
@@ -79,8 +79,6 @@ export type AdjustTone = (args: {
|
|
|
79
79
|
* DynamicColor.
|
|
80
80
|
*/
|
|
81
81
|
export class DynamicColor {
|
|
82
|
-
private readonly hctCache = new Map<Scheme, Hct>();
|
|
83
|
-
|
|
84
82
|
/**
|
|
85
83
|
* The base constructor for DynamicColor.
|
|
86
84
|
*
|
|
@@ -155,7 +153,8 @@ export class DynamicColor {
|
|
|
155
153
|
return new DynamicColor(
|
|
156
154
|
args.name ?? '',
|
|
157
155
|
args.palette,
|
|
158
|
-
args.tone ??
|
|
156
|
+
args.tone ??
|
|
157
|
+
(() => DynamicColor.getInitialToneFromBackground(args.background)),
|
|
159
158
|
args.isBackground ?? false,
|
|
160
159
|
args.chromaMultiplier,
|
|
161
160
|
args.background,
|
|
@@ -165,14 +164,14 @@ export class DynamicColor {
|
|
|
165
164
|
);
|
|
166
165
|
}
|
|
167
166
|
|
|
168
|
-
static getInitialToneFromBackground(
|
|
169
|
-
|
|
170
|
-
):
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
167
|
+
// static getInitialToneFromBackground(
|
|
168
|
+
// background?: () => Color | undefined,
|
|
169
|
+
// ): number {
|
|
170
|
+
// if (background === undefined) {
|
|
171
|
+
// return 50;
|
|
172
|
+
// }
|
|
173
|
+
// return (background() ? background()!.getTone() : 50);
|
|
174
|
+
// }
|
|
176
175
|
|
|
177
176
|
/**
|
|
178
177
|
* Given a background tone, finds a foreground tone, while ensuring they reach
|
|
@@ -270,14 +269,6 @@ export class DynamicColor {
|
|
|
270
269
|
});
|
|
271
270
|
}
|
|
272
271
|
|
|
273
|
-
/**
|
|
274
|
-
* Clears the cache of HCT values for this color. For testing or debugging
|
|
275
|
-
* purposes.
|
|
276
|
-
*/
|
|
277
|
-
clearCache() {
|
|
278
|
-
this.hctCache.clear();
|
|
279
|
-
}
|
|
280
|
-
|
|
281
272
|
/**
|
|
282
273
|
* Returns a ARGB integer (i.e. a hex code).
|
|
283
274
|
*
|
|
@@ -15,9 +15,14 @@
|
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
import {
|
|
19
|
+
clampDouble,
|
|
20
|
+
Contrast,
|
|
21
|
+
DynamicColor,
|
|
22
|
+
} from '@material/material-color-utilities';
|
|
23
|
+
|
|
24
|
+
import { AdjustTone, Color, ColorFromPalette } from '../color';
|
|
25
|
+
import { Context } from 'src/context';
|
|
21
26
|
|
|
22
27
|
/**
|
|
23
28
|
* Describes the different in tone between colors.
|
|
@@ -72,8 +77,8 @@ class ToneDeltaPair {
|
|
|
72
77
|
* one role has two backgrounds.
|
|
73
78
|
*/
|
|
74
79
|
constructor(
|
|
75
|
-
readonly roleA:
|
|
76
|
-
readonly roleB:
|
|
80
|
+
readonly roleA: Color,
|
|
81
|
+
readonly roleB: Color,
|
|
77
82
|
readonly delta: number,
|
|
78
83
|
readonly polarity: TonePolarity,
|
|
79
84
|
readonly stayTogether: boolean,
|
|
@@ -82,29 +87,28 @@ class ToneDeltaPair {
|
|
|
82
87
|
this.constraint = constraint ?? 'exact';
|
|
83
88
|
}
|
|
84
89
|
|
|
85
|
-
adjustedTone({
|
|
86
|
-
scheme,
|
|
87
|
-
dynamicColor,
|
|
88
|
-
}: {
|
|
89
|
-
scheme: Scheme;
|
|
90
|
-
dynamicColor: DynamicColor;
|
|
91
|
-
}) {
|
|
90
|
+
adjustedTone({ context: ctx, color }: { context: Context; color: Color }) {
|
|
92
91
|
const roleA = this.roleA;
|
|
93
92
|
const roleB = this.roleB;
|
|
94
93
|
const polarity = this.polarity;
|
|
95
94
|
const constraint = this.constraint;
|
|
96
95
|
const absoluteDelta =
|
|
97
96
|
polarity === 'darker' ||
|
|
98
|
-
(polarity === 'relative_lighter' &&
|
|
99
|
-
(polarity === 'relative_darker' && !
|
|
97
|
+
(polarity === 'relative_lighter' && ctx.isDark) ||
|
|
98
|
+
(polarity === 'relative_darker' && !ctx.isDark)
|
|
100
99
|
? -this.delta
|
|
101
100
|
: this.delta;
|
|
102
101
|
|
|
103
|
-
const amRoleA =
|
|
102
|
+
const amRoleA = color.name === roleA.name;
|
|
104
103
|
const selfRole = amRoleA ? roleA : roleB;
|
|
105
104
|
const refRole = amRoleA ? roleB : roleA;
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
|
|
106
|
+
if (!(selfRole instanceof ColorFromPalette)) {
|
|
107
|
+
throw new Error('selfRole is not a ColorFromPalette');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
let selfTone = selfRole.options.tone;
|
|
111
|
+
const refTone = refRole.getTone();
|
|
108
112
|
const relativeDelta = absoluteDelta * (amRoleA ? 1 : -1);
|
|
109
113
|
|
|
110
114
|
if (constraint === 'exact') {
|
|
@@ -131,32 +135,31 @@ class ToneDeltaPair {
|
|
|
131
135
|
}
|
|
132
136
|
}
|
|
133
137
|
|
|
134
|
-
if (
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
138
|
+
if (color instanceof ColorFromPalette) {
|
|
139
|
+
if (color.options.background && color.options.contrastCurve) {
|
|
140
|
+
const background = color.options.background;
|
|
141
|
+
const contrastCurve = color.options.contrastCurve;
|
|
142
|
+
if (background && contrastCurve) {
|
|
143
|
+
// Adjust the tones for contrast, if background and contrast curve
|
|
144
|
+
// are defined.
|
|
145
|
+
const bgTone = background.getTone();
|
|
146
|
+
const selfContrast = contrastCurve.get(ctx.contrastLevel);
|
|
147
|
+
selfTone =
|
|
148
|
+
Contrast.ratioOfTones(bgTone, selfTone) >= selfContrast &&
|
|
149
|
+
ctx.contrastLevel >= 0
|
|
150
|
+
? selfTone
|
|
151
|
+
: DynamicColor.foregroundTone(bgTone, selfContrast);
|
|
152
|
+
}
|
|
147
153
|
}
|
|
148
|
-
}
|
|
149
154
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
} else {
|
|
159
|
-
selfTone = clampDouble(0, 49, selfTone);
|
|
155
|
+
// This can avoid the awkward tones for background colors including the
|
|
156
|
+
// access fixed colors. Accent fixed dim colors should not be adjusted.
|
|
157
|
+
if (color.options.isBackground && !color.name.endsWith('_fixed_dim')) {
|
|
158
|
+
if (selfTone >= 57) {
|
|
159
|
+
selfTone = clampDouble(65, 100, selfTone);
|
|
160
|
+
} else {
|
|
161
|
+
selfTone = clampDouble(0, 49, selfTone);
|
|
162
|
+
}
|
|
160
163
|
}
|
|
161
164
|
}
|
|
162
165
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { PaletteManager } from './palette.manager';
|
|
2
|
+
import { Palette, PaletteCallback } from './palette';
|
|
3
|
+
import { Hct } from '../material-color-utilities/htc';
|
|
4
|
+
import { argbFromHex } from '@material/material-color-utilities';
|
|
5
|
+
|
|
6
|
+
export type AddPaletteOptions = Record<string, PaletteCallback>;
|
|
7
|
+
|
|
8
|
+
export class PaletteApi {
|
|
9
|
+
private readonly paletteManager: PaletteManager;
|
|
10
|
+
constructor({ paletteManager }: { paletteManager: PaletteManager }) {
|
|
11
|
+
this.paletteManager = paletteManager;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
add(args: Record<string, PaletteCallback | string>): void {
|
|
15
|
+
Object.entries(args).forEach(([key, callback]) => {
|
|
16
|
+
if (typeof callback === 'string') {
|
|
17
|
+
this.paletteManager.addCustomPalette(
|
|
18
|
+
key,
|
|
19
|
+
Hct.fromInt(argbFromHex(callback)),
|
|
20
|
+
);
|
|
21
|
+
} else {
|
|
22
|
+
this.paletteManager.add(key, callback);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get(
|
|
28
|
+
key:
|
|
29
|
+
| 'primary'
|
|
30
|
+
| 'secondary'
|
|
31
|
+
| 'tertiary'
|
|
32
|
+
| 'neutral'
|
|
33
|
+
| 'neutralVariant'
|
|
34
|
+
| 'error'
|
|
35
|
+
| string,
|
|
36
|
+
): Palette {
|
|
37
|
+
return this.paletteManager.get(key);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
getAll(): Readonly<Record<string, Palette>> {
|
|
41
|
+
return this.paletteManager.palettes;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Context } from 'src/context';
|
|
2
|
+
import { Palette, PaletteCallback } from './palette';
|
|
3
|
+
import { Hct } from '../material-color-utilities/htc';
|
|
4
|
+
import { ColorApi } from '../color';
|
|
5
|
+
|
|
6
|
+
export class PaletteManager {
|
|
7
|
+
_palettes: Record<string, Palette> = {};
|
|
8
|
+
context: Context;
|
|
9
|
+
colorApi: ColorApi;
|
|
10
|
+
|
|
11
|
+
get palettes(): Readonly<Record<string, Palette>> {
|
|
12
|
+
return {
|
|
13
|
+
...this.context.variant.palettes,
|
|
14
|
+
...this._palettes,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
constructor(args: { context: Context; colorApi: ColorApi }) {
|
|
19
|
+
this.colorApi = args.colorApi;
|
|
20
|
+
this.context = args.context;
|
|
21
|
+
|
|
22
|
+
this.context.onUpdate((changed) =>
|
|
23
|
+
Object.entries(this.palettes).forEach(([key, value]) => {
|
|
24
|
+
value.update(changed);
|
|
25
|
+
}),
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
addCustomPalette(key: string, color: Hct) {
|
|
30
|
+
const palette = Palette.fromVariant(key, color, this.context);
|
|
31
|
+
this.add(key, palette);
|
|
32
|
+
this.colorApi.addFromCustomPalette(key);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
add(key: string, palette: PaletteCallback | Palette): void {
|
|
36
|
+
if (this._palettes['key']) {
|
|
37
|
+
throw new Error(`Palette with key ${key} already exists`);
|
|
38
|
+
}
|
|
39
|
+
if (!(palette instanceof Palette))
|
|
40
|
+
palette = new Palette(key, palette, this.context);
|
|
41
|
+
this.set(key, palette);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get(
|
|
45
|
+
key:
|
|
46
|
+
| 'primary'
|
|
47
|
+
| 'secondary'
|
|
48
|
+
| 'tertiary'
|
|
49
|
+
| 'neutral'
|
|
50
|
+
| 'neutralVariant'
|
|
51
|
+
| 'error'
|
|
52
|
+
| string,
|
|
53
|
+
): Palette {
|
|
54
|
+
const palette = this.palettes[key];
|
|
55
|
+
if (!palette) {
|
|
56
|
+
throw new Error(`Palette ${key} not found`);
|
|
57
|
+
}
|
|
58
|
+
return palette;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private set(key: string, palette: Palette) {
|
|
62
|
+
this._palettes[key] = palette;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
update(key: string, args: PaletteCallback | Palette): void {
|
|
66
|
+
if (!this.palettes['key']) {
|
|
67
|
+
throw new Error(`Palette with key ${key} not found`);
|
|
68
|
+
}
|
|
69
|
+
if (!(args instanceof Palette)) {
|
|
70
|
+
args = new Palette(key, args, this.context);
|
|
71
|
+
}
|
|
72
|
+
this.set(key, args);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { asClass } from 'awilix';
|
|
2
|
+
import { Module } from '../app.container';
|
|
3
|
+
import { PaletteManager } from './palette.manager';
|
|
4
|
+
import { PaletteApi } from './palette.api';
|
|
5
|
+
|
|
6
|
+
export const PaletteModule: Module = {
|
|
7
|
+
paletteApi: asClass(PaletteApi).singleton(),
|
|
8
|
+
paletteManager: asClass(PaletteManager).singleton(),
|
|
9
|
+
};
|