@udixio/theme 1.0.0-beta.8 → 1.0.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/.eslintrc.mjs +22 -0
- package/CHANGELOG.md +174 -0
- package/README.md +6 -68
- package/dist/API.d.ts +14 -0
- package/dist/API.d.ts.map +1 -0
- package/dist/LICENSE +202 -0
- package/dist/adapter/adapter.abstract.d.ts +10 -0
- package/dist/adapter/adapter.abstract.d.ts.map +1 -0
- package/dist/adapter/config.interface.d.ts +14 -0
- package/dist/adapter/config.interface.d.ts.map +1 -0
- package/dist/adapter/define-config.d.ts +3 -0
- package/dist/adapter/define-config.d.ts.map +1 -0
- package/dist/adapter/file-adapter.mixin.d.ts +18 -0
- package/dist/adapter/file-adapter.mixin.d.ts.map +1 -0
- package/dist/adapter/index.d.ts +4 -0
- package/dist/adapter/index.d.ts.map +1 -0
- package/dist/adapters/index.d.ts +3 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/node.adapter.d.ts +7 -0
- package/dist/adapters/node.adapter.d.ts.map +1 -0
- package/dist/adapters/vite.adapter.d.ts +3 -0
- package/dist/adapters/vite.adapter.d.ts.map +1 -0
- package/dist/app.container.d.ts +5 -5
- package/dist/app.container.d.ts.map +1 -0
- package/dist/app.module.d.ts +1 -0
- package/dist/app.module.d.ts.map +1 -0
- package/dist/bootstrap.d.ts +3 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/color/color.api.d.ts +39 -0
- package/dist/color/color.api.d.ts.map +1 -0
- package/dist/color/color.manager.d.ts +24 -0
- package/dist/color/color.manager.d.ts.map +1 -0
- package/dist/color/color.module.d.ts +1 -0
- package/dist/color/color.module.d.ts.map +1 -0
- package/dist/color/color.utils.d.ts +8 -0
- package/dist/color/color.utils.d.ts.map +1 -0
- package/dist/color/configurable-color.d.ts +31 -0
- package/dist/color/configurable-color.d.ts.map +1 -0
- package/dist/color/default-color.d.ts +3 -0
- package/dist/color/default-color.d.ts.map +1 -0
- package/dist/color/index.d.ts +5 -4
- package/dist/color/index.d.ts.map +1 -0
- package/dist/index.cjs +3215 -0
- package/dist/index.d.ts +7 -4
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3175 -7
- package/dist/material-color-utilities/contrastCurve.d.ts +1 -0
- package/dist/material-color-utilities/contrastCurve.d.ts.map +1 -0
- package/dist/material-color-utilities/dynamic_color.d.ts +89 -76
- package/dist/material-color-utilities/dynamic_color.d.ts.map +1 -0
- package/dist/material-color-utilities/hct_solver.d.ts +131 -0
- package/dist/material-color-utilities/hct_solver.d.ts.map +1 -0
- package/dist/material-color-utilities/htc.d.ts +77 -0
- package/dist/material-color-utilities/htc.d.ts.map +1 -0
- package/dist/material-color-utilities/index.d.ts +1 -0
- package/dist/material-color-utilities/index.d.ts.map +1 -0
- package/dist/material-color-utilities/toneDeltaPair.d.ts +19 -25
- package/dist/material-color-utilities/toneDeltaPair.d.ts.map +1 -0
- package/dist/plugin/index.d.ts +4 -0
- package/dist/plugin/index.d.ts.map +1 -0
- package/dist/plugin/plugin.abstract.d.ts +19 -5
- package/dist/plugin/plugin.abstract.d.ts.map +1 -0
- package/dist/plugin/plugin.api.d.ts +10 -0
- package/dist/plugin/plugin.api.d.ts.map +1 -0
- package/dist/plugin/plugin.module.d.ts +1 -0
- package/dist/plugin/plugin.module.d.ts.map +1 -0
- package/dist/plugins/font/font.plugin.d.ts +50 -0
- package/dist/plugins/font/font.plugin.d.ts.map +1 -0
- package/dist/plugins/font/index.d.ts +2 -0
- package/dist/plugins/font/index.d.ts.map +1 -0
- package/dist/plugins/index.d.ts +2 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/theme/index.d.ts +7 -3
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/scheme.d.ts +20 -0
- package/dist/theme/scheme.d.ts.map +1 -0
- package/dist/theme/scheme.manager.d.ts +31 -0
- package/dist/theme/scheme.manager.d.ts.map +1 -0
- package/dist/theme/theme.api.d.ts +23 -0
- package/dist/theme/theme.api.d.ts.map +1 -0
- package/dist/theme/theme.module.d.ts +1 -0
- package/dist/theme/theme.module.d.ts.map +1 -0
- package/dist/theme/variant.d.ts +36 -0
- package/dist/theme/variant.d.ts.map +1 -0
- package/dist/theme/variant.manager.d.ts +14 -0
- package/dist/theme/variant.manager.d.ts.map +1 -0
- package/dist/theme/variants/expressive.variant.d.ts +3 -0
- package/dist/theme/variants/expressive.variant.d.ts.map +1 -0
- package/dist/theme/variants/index.d.ts +11 -0
- package/dist/theme/variants/index.d.ts.map +1 -0
- package/dist/theme/variants/neutral.variant.d.ts +3 -0
- package/dist/theme/variants/neutral.variant.d.ts.map +1 -0
- package/dist/theme/variants/tonal-spot.variant.d.ts +3 -0
- package/dist/theme/variants/tonal-spot.variant.d.ts.map +1 -0
- package/dist/theme/variants/vibrant.variant.d.ts +3 -0
- package/dist/theme/variants/vibrant.variant.d.ts.map +1 -0
- package/package.json +24 -86
- package/src/API.ts +23 -0
- package/src/adapter/adapter.abstract.ts +64 -0
- package/src/adapter/config.interface.ts +14 -0
- package/src/adapter/define-config.ts +11 -0
- package/src/adapter/file-adapter.mixin.ts +72 -0
- package/src/adapter/index.ts +3 -0
- package/src/adapters/index.ts +2 -0
- package/src/adapters/node.adapter.ts +49 -0
- package/src/adapters/vite.adapter.ts +79 -0
- package/src/app.container.ts +12 -36
- package/src/app.module.ts +2 -2
- package/src/bootstrap.ts +6 -0
- package/src/color/color.api.ts +75 -0
- package/src/color/color.manager.ts +213 -0
- package/src/color/color.module.ts +4 -4
- package/src/color/color.utils.ts +126 -0
- package/src/color/configurable-color.ts +67 -0
- package/src/color/default-color.ts +832 -0
- package/src/color/index.ts +4 -4
- package/src/index.test.ts +5 -0
- package/src/index.ts +6 -4
- package/src/material-color-utilities/dynamic_color.ts +286 -222
- package/src/material-color-utilities/hct_solver.ts +536 -0
- package/src/material-color-utilities/htc.ts +198 -0
- package/src/material-color-utilities/toneDeltaPair.ts +29 -11
- package/src/plugin/index.ts +3 -0
- package/src/plugin/plugin.abstract.ts +45 -4
- package/src/plugin/plugin.api.ts +51 -0
- package/src/plugin/plugin.module.ts +2 -2
- package/src/plugins/font/font.plugin.ts +203 -0
- package/src/plugins/font/index.ts +1 -0
- package/src/plugins/index.ts +1 -0
- package/src/theme/index.ts +6 -3
- package/src/theme/{services/scheme.service.ts → scheme.manager.ts} +39 -19
- package/src/theme/{entities/scheme.entity.ts → scheme.ts} +20 -4
- package/src/theme/{services/theme.service.ts → theme.api.ts} +23 -19
- package/src/theme/theme.module.ts +6 -4
- package/src/theme/variant.manager.ts +58 -0
- package/src/theme/variant.ts +53 -0
- package/src/theme/variants/expressive.variant.ts +81 -0
- package/src/theme/variants/index.ts +16 -0
- package/src/theme/variants/neutral.variant.ts +45 -0
- package/src/theme/variants/tonal-spot.variant.ts +35 -0
- package/src/theme/variants/vibrant.variant.ts +72 -0
- package/tsconfig.json +13 -0
- package/tsconfig.lib.json +33 -0
- package/tsconfig.spec.json +36 -0
- package/vite.config.ts +54 -0
- package/LICENSE +0 -21
- package/dist/app.service.d.ts +0 -13
- package/dist/color/color.interface.d.ts +0 -8
- package/dist/color/entities/color.entity.d.ts +0 -42
- package/dist/color/entities/index.d.ts +0 -1
- package/dist/color/models/default-color.model.d.ts +0 -3
- package/dist/color/models/index.d.ts +0 -1
- package/dist/color/services/color-manager.service.d.ts +0 -18
- package/dist/color/services/color.service.d.ts +0 -21
- package/dist/color/services/index.d.ts +0 -2
- package/dist/config/config.interface.d.ts +0 -14
- package/dist/config/config.module.d.ts +0 -2
- package/dist/config/config.service.d.ts +0 -12
- package/dist/config/index.d.ts +0 -2
- package/dist/main.d.ts +0 -3
- package/dist/plugin/plugin.service.d.ts +0 -9
- package/dist/theme/entities/index.d.ts +0 -2
- package/dist/theme/entities/scheme.entity.d.ts +0 -15
- package/dist/theme/entities/variant.entity.d.ts +0 -7
- package/dist/theme/models/index.d.ts +0 -1
- package/dist/theme/models/variant.model.d.ts +0 -8
- package/dist/theme/services/index.d.ts +0 -3
- package/dist/theme/services/scheme.service.d.ts +0 -17
- package/dist/theme/services/theme.service.d.ts +0 -22
- package/dist/theme/services/variant.service.d.ts +0 -13
- package/dist/theme.cjs.development.js +0 -1975
- package/dist/theme.cjs.development.js.map +0 -1
- package/dist/theme.cjs.production.min.js +0 -2
- package/dist/theme.cjs.production.min.js.map +0 -1
- package/dist/theme.esm.js +0 -1947
- package/dist/theme.esm.js.map +0 -1
- package/src/app.service.spec.ts +0 -15
- package/src/app.service.ts +0 -23
- package/src/color/color.interface.ts +0 -13
- package/src/color/entities/color.entity.ts +0 -71
- package/src/color/entities/index.ts +0 -1
- package/src/color/models/default-color.model.ts +0 -300
- package/src/color/models/index.ts +0 -1
- package/src/color/services/color-manager.service.ts +0 -191
- package/src/color/services/color.service.spec.ts +0 -28
- package/src/color/services/color.service.ts +0 -75
- package/src/color/services/index.ts +0 -2
- package/src/config/config.interface.ts +0 -15
- package/src/config/config.module.ts +0 -7
- package/src/config/config.service.ts +0 -68
- package/src/config/index.ts +0 -2
- package/src/main.ts +0 -14
- package/src/plugin/plugin.service.ts +0 -26
- package/src/theme/entities/index.ts +0 -2
- package/src/theme/entities/variant.entity.ts +0 -39
- package/src/theme/models/index.ts +0 -1
- package/src/theme/models/variant.model.ts +0 -63
- package/src/theme/services/index.ts +0 -3
- package/src/theme/services/variant.service.ts +0 -52
|
@@ -15,49 +15,92 @@
|
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import {
|
|
19
|
-
clampDouble,
|
|
20
|
-
Contrast,
|
|
21
|
-
Hct,
|
|
22
|
-
TonalPalette,
|
|
23
|
-
} from '@material/material-color-utilities';
|
|
18
|
+
import { clampDouble, Contrast, TonalPalette } from '@material/material-color-utilities';
|
|
24
19
|
import { ContrastCurve } from './contrastCurve';
|
|
25
20
|
import { ToneDeltaPair } from './toneDeltaPair';
|
|
26
|
-
import {
|
|
21
|
+
import { Scheme } from '../theme/scheme';
|
|
22
|
+
import { Hct } from './htc';
|
|
27
23
|
|
|
28
24
|
/**
|
|
29
25
|
* @param name The name of the dynamic color. Defaults to empty.
|
|
30
|
-
* @param palette Function that provides a TonalPalette given
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* @param tone Function that provides a tone given
|
|
35
|
-
*
|
|
36
|
-
*
|
|
26
|
+
* @param palette Function that provides a TonalPalette given DynamicScheme. A
|
|
27
|
+
* TonalPalette is defined by a hue and chroma, so this replaces the need to
|
|
28
|
+
* specify hue/chroma. By providing a tonal palette, when contrast
|
|
29
|
+
* adjustments are made, intended chroma can be preserved.
|
|
30
|
+
* @param tone Function that provides a tone given DynamicScheme. When not
|
|
31
|
+
* provided, the tone is same as the background tone or 50, when no
|
|
32
|
+
* background is provided.
|
|
33
|
+
* @param chromaMultiplier A factor that multiplies the chroma for this color.
|
|
34
|
+
* Default to 1.
|
|
35
|
+
* @param isBackground Whether this dynamic color is a background, with some
|
|
36
|
+
* other color as the foreground. Defaults to false.
|
|
37
37
|
* @param background The background of the dynamic color (as a function of a
|
|
38
|
-
* `
|
|
38
|
+
* `DynamicScheme`), if it exists.
|
|
39
39
|
* @param secondBackground A second background of the dynamic color (as a
|
|
40
|
-
* function of a `
|
|
41
|
-
* exists.
|
|
40
|
+
* function of a `DynamicScheme`), if it exists.
|
|
42
41
|
* @param contrastCurve A `ContrastCurve` object specifying how its contrast
|
|
43
|
-
*
|
|
42
|
+
* against its background should behave in various contrast levels options.
|
|
43
|
+
* Must used together with `background`. When not provided or resolved as
|
|
44
|
+
* undefined, the contrast curve is calculated based on other constraints.
|
|
44
45
|
* @param toneDeltaPair A `ToneDeltaPair` object specifying a tone delta
|
|
45
|
-
*
|
|
46
|
-
*
|
|
46
|
+
* constraint between two colors. One of them must be the color being
|
|
47
|
+
* constructed. When not provided or resolved as undefined, the tone is
|
|
48
|
+
* calculated based on other constraints.
|
|
47
49
|
*/
|
|
48
|
-
interface FromPaletteOptions {
|
|
50
|
+
export interface FromPaletteOptions {
|
|
49
51
|
name?: string;
|
|
50
|
-
palette: (scheme:
|
|
51
|
-
tone
|
|
52
|
+
palette: (scheme: Scheme) => TonalPalette;
|
|
53
|
+
tone?: (scheme: Scheme) => number;
|
|
54
|
+
chromaMultiplier?: (scheme: Scheme) => number;
|
|
52
55
|
isBackground?: boolean;
|
|
53
|
-
background?: (scheme:
|
|
54
|
-
secondBackground?: (scheme:
|
|
55
|
-
contrastCurve?: ContrastCurve;
|
|
56
|
-
toneDeltaPair?: (scheme:
|
|
56
|
+
background?: (scheme: Scheme) => DynamicColor | undefined;
|
|
57
|
+
secondBackground?: (scheme: Scheme) => DynamicColor | undefined;
|
|
58
|
+
contrastCurve?: (scheme: Scheme) => ContrastCurve | undefined;
|
|
59
|
+
toneDeltaPair?: (scheme: Scheme) => ToneDeltaPair | undefined;
|
|
57
60
|
}
|
|
58
61
|
|
|
59
62
|
/**
|
|
60
|
-
*
|
|
63
|
+
* Returns a new DynamicColor that is the same as the original color, but with
|
|
64
|
+
* the extended dynamic color's constraints for the given spec version.
|
|
65
|
+
*
|
|
66
|
+
* @param originlColor The original color.
|
|
67
|
+
* @param specVersion The spec version to extend.
|
|
68
|
+
* @param extendedColor The color with the values to extend.
|
|
69
|
+
*/
|
|
70
|
+
export function extendSpecVersion(
|
|
71
|
+
originlColor: DynamicColor,
|
|
72
|
+
extendedColor: DynamicColor,
|
|
73
|
+
): DynamicColor {
|
|
74
|
+
return DynamicColor.fromPalette({
|
|
75
|
+
name: originlColor.name,
|
|
76
|
+
palette: (s) => extendedColor.palette(s),
|
|
77
|
+
tone: (s) => extendedColor.tone(s),
|
|
78
|
+
isBackground: originlColor.isBackground,
|
|
79
|
+
chromaMultiplier: (s) => {
|
|
80
|
+
const chromaMultiplier = extendedColor.chromaMultiplier;
|
|
81
|
+
return chromaMultiplier !== undefined ? chromaMultiplier(s) : 1;
|
|
82
|
+
},
|
|
83
|
+
background: (s) => {
|
|
84
|
+
const background = extendedColor.background;
|
|
85
|
+
return background !== undefined ? background(s) : undefined;
|
|
86
|
+
},
|
|
87
|
+
secondBackground: (s) => {
|
|
88
|
+
const secondBackground = extendedColor.secondBackground;
|
|
89
|
+
return secondBackground !== undefined ? secondBackground(s) : undefined;
|
|
90
|
+
},
|
|
91
|
+
contrastCurve: (s) => {
|
|
92
|
+
const contrastCurve = extendedColor.contrastCurve;
|
|
93
|
+
return contrastCurve !== undefined ? contrastCurve(s) : undefined;
|
|
94
|
+
},
|
|
95
|
+
toneDeltaPair: (s) => {
|
|
96
|
+
const toneDeltaPair = extendedColor.toneDeltaPair;
|
|
97
|
+
return toneDeltaPair !== undefined ? toneDeltaPair(s) : undefined;
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* A color that adjusts itself based on UI state provided by DynamicScheme.
|
|
61
104
|
*
|
|
62
105
|
* Colors without backgrounds do not change tone when contrast changes. Colors
|
|
63
106
|
* with backgrounds become closer to their background as contrast lowers, and
|
|
@@ -68,7 +111,7 @@ interface FromPaletteOptions {
|
|
|
68
111
|
* DynamicColor.
|
|
69
112
|
*/
|
|
70
113
|
export class DynamicColor {
|
|
71
|
-
private readonly hctCache = new Map<
|
|
114
|
+
private readonly hctCache = new Map<Scheme, Hct>();
|
|
72
115
|
|
|
73
116
|
/**
|
|
74
117
|
* The base constructor for DynamicColor.
|
|
@@ -84,50 +127,52 @@ export class DynamicColor {
|
|
|
84
127
|
* always, in every case.
|
|
85
128
|
*
|
|
86
129
|
* @param name The name of the dynamic color. Defaults to empty.
|
|
87
|
-
* @param palette Function that provides a TonalPalette given
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* @param tone Function that provides a tone, given a
|
|
92
|
-
* @param isBackground Whether this dynamic color is a background, with
|
|
93
|
-
*
|
|
130
|
+
* @param palette Function that provides a TonalPalette given DynamicScheme. A
|
|
131
|
+
* TonalPalette is defined by a hue and chroma, so this replaces the need
|
|
132
|
+
* to specify hue/chroma. By providing a tonal palette, when contrast
|
|
133
|
+
* adjustments are made, intended chroma can be preserved.
|
|
134
|
+
* @param tone Function that provides a tone, given a DynamicScheme.
|
|
135
|
+
* @param isBackground Whether this dynamic color is a background, with some
|
|
136
|
+
* other color as the foreground. Defaults to false.
|
|
137
|
+
* @param chromaMultiplier A factor that multiplies the chroma for this color.
|
|
94
138
|
* @param background The background of the dynamic color (as a function of a
|
|
95
|
-
* `
|
|
139
|
+
* `DynamicScheme`), if it exists.
|
|
96
140
|
* @param secondBackground A second background of the dynamic color (as a
|
|
97
|
-
* function of a `
|
|
98
|
-
* exists.
|
|
141
|
+
* function of a `DynamicScheme`), if it exists.
|
|
99
142
|
* @param contrastCurve A `ContrastCurve` object specifying how its contrast
|
|
100
|
-
*
|
|
143
|
+
* against its background should behave in various contrast levels
|
|
144
|
+
* options.
|
|
101
145
|
* @param toneDeltaPair A `ToneDeltaPair` object specifying a tone delta
|
|
102
|
-
*
|
|
103
|
-
*
|
|
146
|
+
* constraint between two colors. One of them must be the color being
|
|
147
|
+
* constructed.
|
|
104
148
|
*/
|
|
105
149
|
constructor(
|
|
106
150
|
readonly name: string,
|
|
107
|
-
readonly palette: (scheme:
|
|
108
|
-
readonly tone: (scheme:
|
|
151
|
+
readonly palette: (scheme: Scheme) => TonalPalette,
|
|
152
|
+
readonly tone: (scheme: Scheme) => number,
|
|
109
153
|
readonly isBackground: boolean,
|
|
110
|
-
readonly
|
|
111
|
-
readonly
|
|
112
|
-
readonly
|
|
113
|
-
readonly
|
|
154
|
+
readonly chromaMultiplier?: (scheme: Scheme) => number,
|
|
155
|
+
readonly background?: (scheme: Scheme) => DynamicColor | undefined,
|
|
156
|
+
readonly secondBackground?: (scheme: Scheme) => DynamicColor | undefined,
|
|
157
|
+
readonly contrastCurve?: (scheme: Scheme) => ContrastCurve | undefined,
|
|
158
|
+
readonly toneDeltaPair?: (scheme: Scheme) => ToneDeltaPair | undefined,
|
|
114
159
|
) {
|
|
115
160
|
if (!background && secondBackground) {
|
|
116
161
|
throw new Error(
|
|
117
162
|
`Color ${name} has secondBackground` +
|
|
118
|
-
`defined, but background is not defined
|
|
163
|
+
`defined, but background is not defined.`,
|
|
119
164
|
);
|
|
120
165
|
}
|
|
121
166
|
if (!background && contrastCurve) {
|
|
122
167
|
throw new Error(
|
|
123
168
|
`Color ${name} has contrastCurve` +
|
|
124
|
-
`defined, but background is not defined
|
|
169
|
+
`defined, but background is not defined.`,
|
|
125
170
|
);
|
|
126
171
|
}
|
|
127
172
|
if (background && !contrastCurve) {
|
|
128
173
|
throw new Error(
|
|
129
174
|
`Color ${name} has background` +
|
|
130
|
-
`defined, but contrastCurve is not defined
|
|
175
|
+
`defined, but contrastCurve is not defined.`,
|
|
131
176
|
);
|
|
132
177
|
}
|
|
133
178
|
}
|
|
@@ -135,24 +180,34 @@ export class DynamicColor {
|
|
|
135
180
|
/**
|
|
136
181
|
* Create a DynamicColor defined by a TonalPalette and HCT tone.
|
|
137
182
|
*
|
|
138
|
-
* @param args Functions with
|
|
139
|
-
*
|
|
183
|
+
* @param args Functions with DynamicScheme as input. Must provide a palette
|
|
184
|
+
* and tone. May provide a background DynamicColor and ToneDeltaPair.
|
|
140
185
|
*/
|
|
141
186
|
static fromPalette(args: FromPaletteOptions): DynamicColor {
|
|
142
187
|
return new DynamicColor(
|
|
143
188
|
args.name ?? '',
|
|
144
189
|
args.palette,
|
|
145
|
-
args.tone,
|
|
190
|
+
args.tone ?? DynamicColor.getInitialToneFromBackground(args.background),
|
|
146
191
|
args.isBackground ?? false,
|
|
192
|
+
args.chromaMultiplier,
|
|
147
193
|
args.background,
|
|
148
194
|
args.secondBackground,
|
|
149
195
|
args.contrastCurve,
|
|
150
|
-
args.toneDeltaPair
|
|
196
|
+
args.toneDeltaPair,
|
|
151
197
|
);
|
|
152
198
|
}
|
|
153
199
|
|
|
200
|
+
static getInitialToneFromBackground(
|
|
201
|
+
background?: (scheme: Scheme) => DynamicColor | undefined,
|
|
202
|
+
): (scheme: Scheme) => number {
|
|
203
|
+
if (background === undefined) {
|
|
204
|
+
return (s) => 50;
|
|
205
|
+
}
|
|
206
|
+
return (s) => (background(s) ? background(s)!.getTone(s) : 50);
|
|
207
|
+
}
|
|
208
|
+
|
|
154
209
|
/**
|
|
155
|
-
* Given a background tone,
|
|
210
|
+
* Given a background tone, finds a foreground tone, while ensuring they reach
|
|
156
211
|
* a contrast ratio that is as close to [ratio] as possible.
|
|
157
212
|
*
|
|
158
213
|
* @param bgTone Tone in HCT. Range is 0 to 100, undefined behavior when it
|
|
@@ -217,7 +272,7 @@ export class DynamicColor {
|
|
|
217
272
|
}
|
|
218
273
|
|
|
219
274
|
/**
|
|
220
|
-
*
|
|
275
|
+
* Adjusts a tone such that white has 4.5 contrast, if the tone is
|
|
221
276
|
* reasonably close to supporting it.
|
|
222
277
|
*/
|
|
223
278
|
static enableLightForeground(tone: number): number {
|
|
@@ -231,220 +286,229 @@ export class DynamicColor {
|
|
|
231
286
|
}
|
|
232
287
|
|
|
233
288
|
/**
|
|
234
|
-
*
|
|
289
|
+
* Returns a deep copy of this DynamicColor.
|
|
290
|
+
*/
|
|
291
|
+
clone(): DynamicColor {
|
|
292
|
+
return DynamicColor.fromPalette({
|
|
293
|
+
name: this.name,
|
|
294
|
+
palette: this.palette,
|
|
295
|
+
tone: this.tone,
|
|
296
|
+
isBackground: this.isBackground,
|
|
297
|
+
chromaMultiplier: this.chromaMultiplier,
|
|
298
|
+
background: this.background,
|
|
299
|
+
secondBackground: this.secondBackground,
|
|
300
|
+
contrastCurve: this.contrastCurve,
|
|
301
|
+
toneDeltaPair: this.toneDeltaPair,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Clears the cache of HCT values for this color. For testing or debugging
|
|
307
|
+
* purposes.
|
|
308
|
+
*/
|
|
309
|
+
clearCache() {
|
|
310
|
+
this.hctCache.clear();
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Returns a ARGB integer (i.e. a hex code).
|
|
235
315
|
*
|
|
236
316
|
* @param scheme Defines the conditions of the user interface, for example,
|
|
237
|
-
*
|
|
238
|
-
*
|
|
317
|
+
* whether or not it is dark mode or light mode, and what the desired
|
|
318
|
+
* contrast level is.
|
|
239
319
|
*/
|
|
240
|
-
getArgb(scheme:
|
|
320
|
+
getArgb(scheme: Scheme): number {
|
|
241
321
|
return this.getHct(scheme).toInt();
|
|
242
322
|
}
|
|
243
323
|
|
|
244
324
|
/**
|
|
245
|
-
*
|
|
325
|
+
* Returns a color, expressed in the HCT color space, that this
|
|
246
326
|
* DynamicColor is under the conditions in scheme.
|
|
247
327
|
*
|
|
248
328
|
* @param scheme Defines the conditions of the user interface, for example,
|
|
249
|
-
*
|
|
250
|
-
*
|
|
329
|
+
* whether or not it is dark mode or light mode, and what the desired
|
|
330
|
+
* contrast level is.
|
|
251
331
|
*/
|
|
252
|
-
getHct(scheme:
|
|
253
|
-
const
|
|
254
|
-
if (cachedAnswer != null) {
|
|
255
|
-
return cachedAnswer;
|
|
256
|
-
}
|
|
332
|
+
getHct(scheme: Scheme): Hct {
|
|
333
|
+
const palette = this.palette(scheme);
|
|
257
334
|
const tone = this.getTone(scheme);
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
return
|
|
335
|
+
const hue = palette.hue;
|
|
336
|
+
const chroma =
|
|
337
|
+
palette.chroma *
|
|
338
|
+
(this.chromaMultiplier ? this.chromaMultiplier(scheme) : 1);
|
|
339
|
+
|
|
340
|
+
return Hct.from(hue, chroma, tone);
|
|
264
341
|
}
|
|
265
342
|
|
|
266
343
|
/**
|
|
267
|
-
*
|
|
344
|
+
* Returns a tone, T in the HCT color space, that this DynamicColor is under
|
|
268
345
|
* the conditions in scheme.
|
|
269
346
|
*
|
|
270
347
|
* @param scheme Defines the conditions of the user interface, for example,
|
|
271
|
-
*
|
|
272
|
-
*
|
|
348
|
+
* whether or not it is dark mode or light mode, and what the desired
|
|
349
|
+
* contrast level is.
|
|
273
350
|
*/
|
|
274
|
-
getTone(scheme:
|
|
275
|
-
const
|
|
351
|
+
getTone(scheme: Scheme): number {
|
|
352
|
+
const toneDeltaPair = this.toneDeltaPair
|
|
353
|
+
? this.toneDeltaPair(scheme)
|
|
354
|
+
: undefined;
|
|
276
355
|
|
|
277
|
-
// Case
|
|
278
|
-
if (
|
|
279
|
-
const toneDeltaPair = this.toneDeltaPair(scheme);
|
|
356
|
+
// Case 0: tone delta constraint.
|
|
357
|
+
if (toneDeltaPair) {
|
|
280
358
|
const roleA = toneDeltaPair.roleA;
|
|
281
359
|
const roleB = toneDeltaPair.roleB;
|
|
282
|
-
const delta = toneDeltaPair.delta;
|
|
283
360
|
const polarity = toneDeltaPair.polarity;
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
const
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
const
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
: DynamicColor.foregroundTone(bgTone, nContrast);
|
|
309
|
-
// Initial and adjusted tones for `farther`
|
|
310
|
-
const fInitialTone = farther.tone(scheme);
|
|
311
|
-
let fTone =
|
|
312
|
-
Contrast.ratioOfTones(bgTone, fInitialTone) >= fContrast
|
|
313
|
-
? fInitialTone
|
|
314
|
-
: DynamicColor.foregroundTone(bgTone, fContrast);
|
|
315
|
-
|
|
316
|
-
if (decreasingContrast) {
|
|
317
|
-
// If decreasing contrast, adjust color to the "bare minimum"
|
|
318
|
-
// that satisfies contrast.
|
|
319
|
-
nTone = DynamicColor.foregroundTone(bgTone, nContrast);
|
|
320
|
-
fTone = DynamicColor.foregroundTone(bgTone, fContrast);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
if ((fTone - nTone) * expansionDir >= delta) {
|
|
324
|
-
// Good! Tones satisfy the constraint; no change needed.
|
|
325
|
-
} else {
|
|
326
|
-
// 2nd round: expand farther to match delta.
|
|
327
|
-
fTone = clampDouble(0, 100, nTone + delta * expansionDir);
|
|
328
|
-
if ((fTone - nTone) * expansionDir >= delta) {
|
|
329
|
-
// Good! Tones now satisfy the constraint; no change needed.
|
|
361
|
+
const constraint = toneDeltaPair.constraint;
|
|
362
|
+
const absoluteDelta =
|
|
363
|
+
polarity === 'darker' ||
|
|
364
|
+
(polarity === 'relative_lighter' && scheme.isDark) ||
|
|
365
|
+
(polarity === 'relative_darker' && !scheme.isDark)
|
|
366
|
+
? -toneDeltaPair.delta
|
|
367
|
+
: toneDeltaPair.delta;
|
|
368
|
+
|
|
369
|
+
const amRoleA = this.name === roleA.name;
|
|
370
|
+
const selfRole = amRoleA ? roleA : roleB;
|
|
371
|
+
const refRole = amRoleA ? roleB : roleA;
|
|
372
|
+
let selfTone = selfRole.tone(scheme);
|
|
373
|
+
const refTone = refRole.getTone(scheme);
|
|
374
|
+
const relativeDelta = absoluteDelta * (amRoleA ? 1 : -1);
|
|
375
|
+
|
|
376
|
+
if (constraint === 'exact') {
|
|
377
|
+
selfTone = clampDouble(0, 100, refTone + relativeDelta);
|
|
378
|
+
} else if (constraint === 'nearer') {
|
|
379
|
+
if (relativeDelta > 0) {
|
|
380
|
+
selfTone = clampDouble(
|
|
381
|
+
0,
|
|
382
|
+
100,
|
|
383
|
+
clampDouble(refTone, refTone + relativeDelta, selfTone),
|
|
384
|
+
);
|
|
330
385
|
} else {
|
|
331
|
-
|
|
332
|
-
|
|
386
|
+
selfTone = clampDouble(
|
|
387
|
+
0,
|
|
388
|
+
100,
|
|
389
|
+
clampDouble(refTone + relativeDelta, refTone, selfTone),
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
} else if (constraint === 'farther') {
|
|
393
|
+
if (relativeDelta > 0) {
|
|
394
|
+
selfTone = clampDouble(refTone + relativeDelta, 100, selfTone);
|
|
395
|
+
} else {
|
|
396
|
+
selfTone = clampDouble(0, refTone + relativeDelta, selfTone);
|
|
333
397
|
}
|
|
334
398
|
}
|
|
335
399
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
400
|
+
if (this.background && this.contrastCurve) {
|
|
401
|
+
const background = this.background(scheme);
|
|
402
|
+
const contrastCurve = this.contrastCurve(scheme);
|
|
403
|
+
if (background && contrastCurve) {
|
|
404
|
+
// Adjust the tones for contrast, if background and contrast curve
|
|
405
|
+
// are defined.
|
|
406
|
+
const bgTone = background.getTone(scheme);
|
|
407
|
+
const selfContrast = contrastCurve.get(scheme.contrastLevel);
|
|
408
|
+
selfTone =
|
|
409
|
+
Contrast.ratioOfTones(bgTone, selfTone) >= selfContrast &&
|
|
410
|
+
scheme.contrastLevel >= 0
|
|
411
|
+
? selfTone
|
|
412
|
+
: DynamicColor.foregroundTone(bgTone, selfContrast);
|
|
346
413
|
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
} else {
|
|
355
|
-
nTone = 49;
|
|
356
|
-
fTone = Math.min(fTone, nTone + delta * expansionDir);
|
|
357
|
-
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// This can avoid the awkward tones for background colors including the
|
|
417
|
+
// access fixed colors. Accent fixed dim colors should not be adjusted.
|
|
418
|
+
if (this.isBackground && !this.name.endsWith('_fixed_dim')) {
|
|
419
|
+
if (selfTone >= 57) {
|
|
420
|
+
selfTone = clampDouble(65, 100, selfTone);
|
|
358
421
|
} else {
|
|
359
|
-
|
|
360
|
-
if (expansionDir > 0) {
|
|
361
|
-
fTone = 60;
|
|
362
|
-
} else {
|
|
363
|
-
fTone = 49;
|
|
364
|
-
}
|
|
422
|
+
selfTone = clampDouble(0, 49, selfTone);
|
|
365
423
|
}
|
|
366
424
|
}
|
|
367
425
|
|
|
368
|
-
|
|
369
|
-
return amNearer ? nTone : fTone;
|
|
426
|
+
return selfTone;
|
|
370
427
|
} else {
|
|
371
|
-
// Case
|
|
428
|
+
// Case 1: No tone delta pair; just solve for itself.
|
|
372
429
|
let answer = this.tone(scheme);
|
|
373
430
|
|
|
374
|
-
if (
|
|
431
|
+
if (
|
|
432
|
+
this.background == undefined ||
|
|
433
|
+
this.background(scheme) === undefined ||
|
|
434
|
+
this.contrastCurve == undefined ||
|
|
435
|
+
this.contrastCurve(scheme) === undefined
|
|
436
|
+
) {
|
|
375
437
|
return answer; // No adjustment for colors with no background.
|
|
376
438
|
}
|
|
377
439
|
|
|
378
|
-
const bgTone = this.background(scheme)
|
|
379
|
-
|
|
380
|
-
|
|
440
|
+
const bgTone = this.background(scheme)!.getTone(scheme);
|
|
441
|
+
const desiredRatio = this.contrastCurve(scheme)!.get(
|
|
442
|
+
scheme.contrastLevel,
|
|
443
|
+
);
|
|
381
444
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
445
|
+
// Recalculate the tone from desired contrast ratio if the current
|
|
446
|
+
// contrast ratio is not enough or desired contrast level is decreasing
|
|
447
|
+
// (<0).
|
|
448
|
+
answer =
|
|
449
|
+
Contrast.ratioOfTones(bgTone, answer) >= desiredRatio &&
|
|
450
|
+
scheme.contrastLevel >= 0
|
|
451
|
+
? answer
|
|
452
|
+
: DynamicColor.foregroundTone(bgTone, desiredRatio);
|
|
453
|
+
|
|
454
|
+
// This can avoid the awkward tones for background colors including the
|
|
455
|
+
// access fixed colors. Accent fixed dim colors should not be adjusted.
|
|
456
|
+
if (this.isBackground && !this.name.endsWith('_fixed_dim')) {
|
|
457
|
+
if (answer >= 57) {
|
|
458
|
+
answer = clampDouble(65, 100, answer);
|
|
459
|
+
} else {
|
|
460
|
+
answer = clampDouble(0, 49, answer);
|
|
461
|
+
}
|
|
387
462
|
}
|
|
388
463
|
|
|
389
|
-
if (
|
|
390
|
-
|
|
464
|
+
if (
|
|
465
|
+
this.secondBackground == undefined ||
|
|
466
|
+
this.secondBackground(scheme) === undefined
|
|
467
|
+
) {
|
|
468
|
+
return answer;
|
|
391
469
|
}
|
|
392
470
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
471
|
+
// Case 2: Adjust for dual backgrounds.
|
|
472
|
+
const [bg1, bg2] = [this.background, this.secondBackground];
|
|
473
|
+
const [bgTone1, bgTone2] = [
|
|
474
|
+
bg1(scheme)!.getTone(scheme),
|
|
475
|
+
bg2(scheme)!.getTone(scheme),
|
|
476
|
+
];
|
|
477
|
+
const [upper, lower] = [
|
|
478
|
+
Math.max(bgTone1, bgTone2),
|
|
479
|
+
Math.min(bgTone1, bgTone2),
|
|
480
|
+
];
|
|
481
|
+
|
|
482
|
+
if (
|
|
483
|
+
Contrast.ratioOfTones(upper, answer) >= desiredRatio &&
|
|
484
|
+
Contrast.ratioOfTones(lower, answer) >= desiredRatio
|
|
485
|
+
) {
|
|
486
|
+
return answer;
|
|
400
487
|
}
|
|
401
488
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
const [bg1, bg2] = [this.background, this.secondBackground];
|
|
406
|
-
const [bgTone1, bgTone2] = [
|
|
407
|
-
bg1(scheme).getTone(scheme),
|
|
408
|
-
bg2(scheme).getTone(scheme),
|
|
409
|
-
];
|
|
410
|
-
const [upper, lower] = [
|
|
411
|
-
Math.max(bgTone1, bgTone2),
|
|
412
|
-
Math.min(bgTone1, bgTone2),
|
|
413
|
-
];
|
|
414
|
-
|
|
415
|
-
if (
|
|
416
|
-
Contrast.ratioOfTones(upper, answer) >= desiredRatio &&
|
|
417
|
-
Contrast.ratioOfTones(lower, answer) >= desiredRatio
|
|
418
|
-
) {
|
|
419
|
-
return answer;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
// The darkest light tone that satisfies the desired ratio,
|
|
423
|
-
// or -1 if such ratio cannot be reached.
|
|
424
|
-
const lightOption = Contrast.lighter(upper, desiredRatio);
|
|
489
|
+
// The darkest light tone that satisfies the desired ratio,
|
|
490
|
+
// or -1 if such ratio cannot be reached.
|
|
491
|
+
const lightOption = Contrast.lighter(upper, desiredRatio);
|
|
425
492
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
493
|
+
// The lightest dark tone that satisfies the desired ratio,
|
|
494
|
+
// or -1 if such ratio cannot be reached.
|
|
495
|
+
const darkOption = Contrast.darker(lower, desiredRatio);
|
|
429
496
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
497
|
+
// Tones suitable for the foreground.
|
|
498
|
+
const availables = [];
|
|
499
|
+
if (lightOption !== -1) availables.push(lightOption);
|
|
500
|
+
if (darkOption !== -1) availables.push(darkOption);
|
|
434
501
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
}
|
|
441
|
-
if (availables.length === 1) {
|
|
442
|
-
return availables[0];
|
|
443
|
-
}
|
|
444
|
-
return darkOption < 0 ? 0 : darkOption;
|
|
502
|
+
const prefersLight =
|
|
503
|
+
DynamicColor.tonePrefersLightForeground(bgTone1) ||
|
|
504
|
+
DynamicColor.tonePrefersLightForeground(bgTone2);
|
|
505
|
+
if (prefersLight) {
|
|
506
|
+
return lightOption < 0 ? 100 : lightOption;
|
|
445
507
|
}
|
|
446
|
-
|
|
447
|
-
|
|
508
|
+
if (availables.length === 1) {
|
|
509
|
+
return availables[0];
|
|
510
|
+
}
|
|
511
|
+
return darkOption < 0 ? 0 : darkOption;
|
|
448
512
|
}
|
|
449
513
|
}
|
|
450
514
|
}
|