@udixio/theme 1.0.0-beta.2
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/LICENSE +21 -0
- package/README.md +73 -0
- package/dist/app.module.d.ts +2 -0
- package/dist/app.service.d.ts +7 -0
- package/dist/color/color-manager.service.d.ts +15 -0
- package/dist/color/color.interface.d.ts +9 -0
- package/dist/color/color.module.d.ts +2 -0
- package/dist/color/color.service.d.ts +13 -0
- package/dist/color/entities/color.entity.d.ts +37 -0
- package/dist/color/models/default-color.model.d.ts +4 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +8 -0
- package/dist/main.d.ts +2 -0
- package/dist/material-color-utilities/contrastCurve.d.ts +46 -0
- package/dist/material-color-utilities/dynamic_color.d.ts +171 -0
- package/dist/material-color-utilities/index.d.ts +2 -0
- package/dist/material-color-utilities/toneDeltaPair.d.ts +60 -0
- package/dist/theme/entities/scheme.entity.d.ts +15 -0
- package/dist/theme/entities/variant.entity.d.ts +6 -0
- package/dist/theme/models/variant.model.d.ts +8 -0
- package/dist/theme/services/scheme.service.d.ts +12 -0
- package/dist/theme/services/theme.service.d.ts +13 -0
- package/dist/theme/services/variant.service.d.ts +7 -0
- package/dist/theme/theme.module.d.ts +2 -0
- package/dist/theme.cjs.development.js +1310 -0
- package/dist/theme.cjs.development.js.map +1 -0
- package/dist/theme.cjs.production.min.js +2 -0
- package/dist/theme.cjs.production.min.js.map +1 -0
- package/dist/theme.esm.js +1306 -0
- package/dist/theme.esm.js.map +1 -0
- package/package.json +101 -0
- package/src/app.module.ts +10 -0
- package/src/app.service.spec.ts +15 -0
- package/src/app.service.ts +11 -0
- package/src/color/color-manager.service.ts +186 -0
- package/src/color/color.interface.ts +15 -0
- package/src/color/color.module.ts +11 -0
- package/src/color/color.service.spec.ts +28 -0
- package/src/color/color.service.ts +52 -0
- package/src/color/entities/color.entity.ts +60 -0
- package/src/color/models/default-color.model.ts +297 -0
- package/src/index.ts +1 -0
- package/src/main.ts +11 -0
- package/src/material-color-utilities/contrastCurve.ts +63 -0
- package/src/material-color-utilities/dynamic_color.ts +450 -0
- package/src/material-color-utilities/index.ts +2 -0
- package/src/material-color-utilities/toneDeltaPair.ts +64 -0
- package/src/theme/entities/scheme.entity.ts +44 -0
- package/src/theme/entities/variant.entity.ts +38 -0
- package/src/theme/models/variant.model.ts +56 -0
- package/src/theme/services/scheme.service.ts +52 -0
- package/src/theme/services/theme.service.ts +58 -0
- package/src/theme/services/variant.service.ts +17 -0
- package/src/theme/theme.module.ts +10 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { hexFromArgb, TonalPalette } from '@material/material-color-utilities';
|
|
2
|
+
import { SchemeEntity } from '../../theme/entities/scheme.entity';
|
|
3
|
+
import { DynamicColor } from '../../material-color-utilities/dynamic_color';
|
|
4
|
+
import { ContrastCurve } from '../../material-color-utilities';
|
|
5
|
+
import mergeDeep from 'merge-deep';
|
|
6
|
+
import { SchemeService } from '../../theme/services/scheme.service';
|
|
7
|
+
import { ColorManagerService } from '../color-manager.service';
|
|
8
|
+
|
|
9
|
+
export interface ColorOptions {
|
|
10
|
+
palette: (scheme: SchemeEntity) => TonalPalette;
|
|
11
|
+
tone: (scheme: SchemeEntity) => number;
|
|
12
|
+
isBackground?: boolean;
|
|
13
|
+
background?: (scheme: SchemeEntity) => DynamicColor;
|
|
14
|
+
secondBackground?: (scheme: SchemeEntity) => DynamicColor;
|
|
15
|
+
contrastCurve?: ContrastCurve;
|
|
16
|
+
toneDeltaPair?: (scheme: SchemeEntity) => {
|
|
17
|
+
roleA: DynamicColor;
|
|
18
|
+
readonly roleB: DynamicColor;
|
|
19
|
+
readonly delta: number;
|
|
20
|
+
readonly polarity: 'darker' | 'lighter' | 'nearer' | 'farther';
|
|
21
|
+
readonly stayTogether: boolean;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export class ColorEntity {
|
|
26
|
+
private dynamicColor: DynamicColor | null = null;
|
|
27
|
+
|
|
28
|
+
constructor(
|
|
29
|
+
private option: ColorOptions & { name: string },
|
|
30
|
+
private schemeService: SchemeService,
|
|
31
|
+
private colorService: ColorManagerService
|
|
32
|
+
) {}
|
|
33
|
+
|
|
34
|
+
update(args: Partial<ColorOptions & { name: string }>) {
|
|
35
|
+
this.dynamicColor = null;
|
|
36
|
+
this.option = mergeDeep(this.option, args);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
getHex(): string {
|
|
40
|
+
return hexFromArgb(this.getArgb());
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getArgb() {
|
|
44
|
+
return this.getDynamicColor().getArgb(this.schemeService.get());
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
getName(): string {
|
|
48
|
+
return this.option.name.replace(/([A-Z])/g, '_$1').toLowerCase();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
getDynamicColor(): DynamicColor {
|
|
52
|
+
if (!this.dynamicColor) {
|
|
53
|
+
this.dynamicColor = DynamicColor.fromPalette({
|
|
54
|
+
...this.option,
|
|
55
|
+
name: this.getName(),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return this.dynamicColor;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { DislikeAnalyzer, Hct } from '@material/material-color-utilities';
|
|
2
|
+
import { ContrastCurve, ToneDeltaPair } from '../../material-color-utilities';
|
|
3
|
+
import { DynamicColor } from '../../material-color-utilities/dynamic_color';
|
|
4
|
+
import { ColorOptions } from '../entities/color.entity';
|
|
5
|
+
import { ColorManagerService, highestSurface } from '../color-manager.service';
|
|
6
|
+
|
|
7
|
+
export type DynamicColorKey =
|
|
8
|
+
| 'background'
|
|
9
|
+
| 'onBackground'
|
|
10
|
+
| 'surface'
|
|
11
|
+
| 'surfaceDim'
|
|
12
|
+
| 'surfaceBright'
|
|
13
|
+
| 'surfaceContainerLowest'
|
|
14
|
+
| 'surfaceContainerLow'
|
|
15
|
+
| 'surfaceContainer'
|
|
16
|
+
| 'surfaceContainerHigh'
|
|
17
|
+
| 'surfaceContainerHighest'
|
|
18
|
+
| 'onSurface'
|
|
19
|
+
| 'surfaceVariant'
|
|
20
|
+
| 'onSurfaceVariant'
|
|
21
|
+
| 'inverseSurface'
|
|
22
|
+
| 'inverseOnSurface'
|
|
23
|
+
| 'outline'
|
|
24
|
+
| 'outlineVariant'
|
|
25
|
+
| 'shadow'
|
|
26
|
+
| 'scrim'
|
|
27
|
+
| 'surfaceTint'
|
|
28
|
+
| 'primary'
|
|
29
|
+
| 'onPrimary'
|
|
30
|
+
| 'primaryContainer'
|
|
31
|
+
| 'onPrimaryContainer'
|
|
32
|
+
| 'inversePrimary'
|
|
33
|
+
| 'secondary'
|
|
34
|
+
| 'onSecondary'
|
|
35
|
+
| 'secondaryContainer'
|
|
36
|
+
| 'onSecondaryContainer'
|
|
37
|
+
| 'tertiary'
|
|
38
|
+
| 'onTertiary'
|
|
39
|
+
| 'tertiaryContainer'
|
|
40
|
+
| 'onTertiaryContainer'
|
|
41
|
+
| 'error'
|
|
42
|
+
| 'onError'
|
|
43
|
+
| 'errorContainer'
|
|
44
|
+
| 'onErrorContainer'
|
|
45
|
+
| 'primaryFixed'
|
|
46
|
+
| 'primaryFixedDim'
|
|
47
|
+
| 'onPrimaryFixed'
|
|
48
|
+
| 'onPrimaryFixedVariant'
|
|
49
|
+
| 'secondaryFixed'
|
|
50
|
+
| 'secondaryFixedDim'
|
|
51
|
+
| 'onSecondaryFixed'
|
|
52
|
+
| 'onSecondaryFixedVariant'
|
|
53
|
+
| 'tertiaryFixed'
|
|
54
|
+
| 'tertiaryFixedDim'
|
|
55
|
+
| 'onTertiaryFixed'
|
|
56
|
+
| 'onTertiaryFixedVariant';
|
|
57
|
+
|
|
58
|
+
function findDesiredChromaByTone(
|
|
59
|
+
hue: number,
|
|
60
|
+
chroma: number,
|
|
61
|
+
tone: number,
|
|
62
|
+
byDecreasingTone: boolean
|
|
63
|
+
): number {
|
|
64
|
+
let answer = tone;
|
|
65
|
+
|
|
66
|
+
let closestToChroma = Hct.from(hue, chroma, tone);
|
|
67
|
+
if (closestToChroma.chroma < chroma) {
|
|
68
|
+
let chromaPeak = closestToChroma.chroma;
|
|
69
|
+
while (closestToChroma.chroma < chroma) {
|
|
70
|
+
answer += byDecreasingTone ? -1.0 : 1.0;
|
|
71
|
+
const potentialSolution = Hct.from(hue, chroma, answer);
|
|
72
|
+
if (chromaPeak > potentialSolution.chroma) {
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
if (Math.abs(potentialSolution.chroma - chroma) < 0.4) {
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const potentialDelta = Math.abs(potentialSolution.chroma - chroma);
|
|
80
|
+
const currentDelta = Math.abs(closestToChroma.chroma - chroma);
|
|
81
|
+
if (potentialDelta < currentDelta) {
|
|
82
|
+
closestToChroma = potentialSolution;
|
|
83
|
+
}
|
|
84
|
+
chromaPeak = Math.max(chromaPeak, potentialSolution.chroma);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return answer;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export const DefaultColors = (
|
|
92
|
+
colorManagerService: ColorManagerService
|
|
93
|
+
): Partial<Record<DynamicColorKey, Partial<Omit<ColorOptions, 'name'>>>> => ({
|
|
94
|
+
background: {
|
|
95
|
+
palette: (s) => s.getPalette('neutral'),
|
|
96
|
+
tone: (s) => (s.isDark ? 6 : 98),
|
|
97
|
+
isBackground: true,
|
|
98
|
+
},
|
|
99
|
+
onBackground: {
|
|
100
|
+
palette: (s) => s.getPalette('neutral'),
|
|
101
|
+
tone: (s) => (s.isDark ? 90 : 10),
|
|
102
|
+
background: (s) => colorManagerService.get('background').getDynamicColor(),
|
|
103
|
+
contrastCurve: new ContrastCurve(3, 3, 4.5, 7),
|
|
104
|
+
},
|
|
105
|
+
surface: {
|
|
106
|
+
palette: (s) => s.getPalette('neutral'),
|
|
107
|
+
tone: (s) => (s.isDark ? 6 : 98),
|
|
108
|
+
isBackground: true,
|
|
109
|
+
},
|
|
110
|
+
surfaceDim: {
|
|
111
|
+
palette: (s) => s.getPalette('neutral'),
|
|
112
|
+
tone: (s) => (s.isDark ? 6 : 87),
|
|
113
|
+
isBackground: true,
|
|
114
|
+
},
|
|
115
|
+
surfaceBright: {
|
|
116
|
+
palette: (s) => s.getPalette('neutral'),
|
|
117
|
+
tone: (s) => (s.isDark ? 24 : 98),
|
|
118
|
+
isBackground: true,
|
|
119
|
+
},
|
|
120
|
+
surfaceContainerLowest: {
|
|
121
|
+
palette: (s) => s.getPalette('neutral'),
|
|
122
|
+
tone: (s) => (s.isDark ? 4 : 100),
|
|
123
|
+
isBackground: true,
|
|
124
|
+
},
|
|
125
|
+
surfaceContainerLow: {
|
|
126
|
+
palette: (s) => s.getPalette('neutral'),
|
|
127
|
+
tone: (s) => (s.isDark ? 10 : 96),
|
|
128
|
+
isBackground: true,
|
|
129
|
+
},
|
|
130
|
+
surfaceContainer: {
|
|
131
|
+
palette: (s) => s.getPalette('neutral'),
|
|
132
|
+
tone: (s) => (s.isDark ? 12 : 94),
|
|
133
|
+
isBackground: true,
|
|
134
|
+
},
|
|
135
|
+
surfaceContainerHigh: {
|
|
136
|
+
palette: (s) => s.getPalette('neutral'),
|
|
137
|
+
tone: (s) => (s.isDark ? 17 : 92),
|
|
138
|
+
isBackground: true,
|
|
139
|
+
},
|
|
140
|
+
surfaceContainerHighest: {
|
|
141
|
+
palette: (s) => s.getPalette('neutral'),
|
|
142
|
+
tone: (s) => (s.isDark ? 22 : 90),
|
|
143
|
+
isBackground: true,
|
|
144
|
+
},
|
|
145
|
+
onSurface: {
|
|
146
|
+
palette: (s) => s.getPalette('neutral'),
|
|
147
|
+
tone: (s) => (s.isDark ? 90 : 10),
|
|
148
|
+
background: (s) => highestSurface(s, colorManagerService),
|
|
149
|
+
contrastCurve: new ContrastCurve(4.5, 7, 11, 21),
|
|
150
|
+
},
|
|
151
|
+
surfaceVariant: {
|
|
152
|
+
palette: (s) => s.getPalette('neutralVariant'),
|
|
153
|
+
tone: (s) => (s.isDark ? 30 : 90),
|
|
154
|
+
isBackground: true,
|
|
155
|
+
},
|
|
156
|
+
onSurfaceVariant: {
|
|
157
|
+
palette: (s) => s.getPalette('neutralVariant'),
|
|
158
|
+
tone: (s) => (s.isDark ? 80 : 30),
|
|
159
|
+
background: (s) => highestSurface(s, colorManagerService),
|
|
160
|
+
contrastCurve: new ContrastCurve(3, 4.5, 7, 11),
|
|
161
|
+
},
|
|
162
|
+
inverseSurface: {
|
|
163
|
+
palette: (s) => s.getPalette('neutral'),
|
|
164
|
+
tone: (s) => (s.isDark ? 90 : 20),
|
|
165
|
+
},
|
|
166
|
+
inverseOnSurface: {
|
|
167
|
+
palette: (s) => s.getPalette('neutral'),
|
|
168
|
+
tone: (s) => (s.isDark ? 20 : 95),
|
|
169
|
+
background: (s) =>
|
|
170
|
+
colorManagerService.get('inverseSurface').getDynamicColor(),
|
|
171
|
+
contrastCurve: new ContrastCurve(4.5, 7, 11, 21),
|
|
172
|
+
},
|
|
173
|
+
outline: {
|
|
174
|
+
palette: (s) => s.getPalette('neutralVariant'),
|
|
175
|
+
tone: (s) => (s.isDark ? 60 : 50),
|
|
176
|
+
background: (s) => highestSurface(s, colorManagerService),
|
|
177
|
+
contrastCurve: new ContrastCurve(1.5, 3, 4.5, 7),
|
|
178
|
+
},
|
|
179
|
+
outlineVariant: {
|
|
180
|
+
palette: (s) => s.getPalette('neutralVariant'),
|
|
181
|
+
tone: (s) => (s.isDark ? 30 : 80),
|
|
182
|
+
background: (s) => highestSurface(s, colorManagerService),
|
|
183
|
+
contrastCurve: new ContrastCurve(1, 1, 3, 7),
|
|
184
|
+
},
|
|
185
|
+
shadow: {
|
|
186
|
+
palette: (s) => s.getPalette('neutral'),
|
|
187
|
+
tone: (s) => 0,
|
|
188
|
+
},
|
|
189
|
+
scrim: {
|
|
190
|
+
palette: (s) => s.getPalette('neutral'),
|
|
191
|
+
tone: (s) => 0,
|
|
192
|
+
},
|
|
193
|
+
surfaceTint: {
|
|
194
|
+
palette: (s) => s.getPalette('neutral'),
|
|
195
|
+
tone: (s) => (s.isDark ? 80 : 40),
|
|
196
|
+
isBackground: true,
|
|
197
|
+
},
|
|
198
|
+
secondaryContainer: {
|
|
199
|
+
tone: (s) => {
|
|
200
|
+
const initialTone = s.isDark ? 30 : 90;
|
|
201
|
+
return findDesiredChromaByTone(
|
|
202
|
+
s.getPalette('secondary').hue,
|
|
203
|
+
s.getPalette('secondary').chroma,
|
|
204
|
+
initialTone,
|
|
205
|
+
!s.isDark
|
|
206
|
+
);
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
onSecondaryContainer: {
|
|
210
|
+
tone: (s) => {
|
|
211
|
+
return DynamicColor.foregroundTone(
|
|
212
|
+
colorManagerService.get('secondaryContainer').getDynamicColor().tone(s),
|
|
213
|
+
4.5
|
|
214
|
+
);
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
tertiaryContainer: {
|
|
218
|
+
palette: (s) => s.getPalette('tertiary'),
|
|
219
|
+
tone: (s) => {
|
|
220
|
+
const proposedHct = s
|
|
221
|
+
.getPalette('tertiary')
|
|
222
|
+
.getHct(s.sourceColorHct.tone);
|
|
223
|
+
return DislikeAnalyzer.fixIfDisliked(proposedHct).tone;
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
onTertiaryContainer: {
|
|
227
|
+
palette: (s) => s.getPalette('tertiary'),
|
|
228
|
+
tone: (s) => {
|
|
229
|
+
return DynamicColor.foregroundTone(
|
|
230
|
+
colorManagerService.get('tertiaryContainer').getDynamicColor().tone(s),
|
|
231
|
+
4.5
|
|
232
|
+
);
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
error: {
|
|
236
|
+
palette: (s) => s.getPalette('error'),
|
|
237
|
+
tone: (s) => (s.isDark ? 80 : 40),
|
|
238
|
+
isBackground: true,
|
|
239
|
+
background: (s) => highestSurface(s, colorManagerService),
|
|
240
|
+
contrastCurve: new ContrastCurve(3, 4.5, 7, 11),
|
|
241
|
+
toneDeltaPair: (s) =>
|
|
242
|
+
new ToneDeltaPair(
|
|
243
|
+
colorManagerService.get('errorContainer').getDynamicColor(),
|
|
244
|
+
colorManagerService.get('error').getDynamicColor(),
|
|
245
|
+
15,
|
|
246
|
+
'nearer',
|
|
247
|
+
false
|
|
248
|
+
),
|
|
249
|
+
},
|
|
250
|
+
onError: {
|
|
251
|
+
palette: (s) => s.getPalette('error'),
|
|
252
|
+
tone: (s) => (s.isDark ? 20 : 100),
|
|
253
|
+
background: (s) => colorManagerService.get('error').getDynamicColor(),
|
|
254
|
+
contrastCurve: new ContrastCurve(4.5, 7, 11, 21),
|
|
255
|
+
},
|
|
256
|
+
errorContainer: {
|
|
257
|
+
palette: (s) => s.getPalette('error'),
|
|
258
|
+
tone: (s) => (s.isDark ? 30 : 90),
|
|
259
|
+
isBackground: true,
|
|
260
|
+
background: (s) => highestSurface(s, colorManagerService),
|
|
261
|
+
contrastCurve: new ContrastCurve(1, 1, 3, 7),
|
|
262
|
+
toneDeltaPair: (s) =>
|
|
263
|
+
new ToneDeltaPair(
|
|
264
|
+
colorManagerService.get('errorContainer').getDynamicColor(),
|
|
265
|
+
colorManagerService.get('error').getDynamicColor(),
|
|
266
|
+
15,
|
|
267
|
+
'nearer',
|
|
268
|
+
false
|
|
269
|
+
),
|
|
270
|
+
},
|
|
271
|
+
onErrorContainer: {
|
|
272
|
+
palette: (s) => s.getPalette('error'),
|
|
273
|
+
tone: (s) => (s.isDark ? 90 : 10),
|
|
274
|
+
background: (s) =>
|
|
275
|
+
colorManagerService.get('errorContainer').getDynamicColor(),
|
|
276
|
+
contrastCurve: new ContrastCurve(4.5, 7, 11, 21),
|
|
277
|
+
},
|
|
278
|
+
|
|
279
|
+
onTertiaryFixed: {
|
|
280
|
+
palette: (s) => s.getPalette('tertiary'),
|
|
281
|
+
tone: (s) => 10.0,
|
|
282
|
+
background: (s) =>
|
|
283
|
+
colorManagerService.get('tertiaryFixedDim').getDynamicColor(),
|
|
284
|
+
secondBackground: (s) =>
|
|
285
|
+
colorManagerService.get('tertiaryFixed').getDynamicColor(),
|
|
286
|
+
contrastCurve: new ContrastCurve(4.5, 7, 11, 21),
|
|
287
|
+
},
|
|
288
|
+
onTertiaryFixedVariant: {
|
|
289
|
+
palette: (s) => s.getPalette('tertiary'),
|
|
290
|
+
tone: (s) => 30.0,
|
|
291
|
+
background: (s) =>
|
|
292
|
+
colorManagerService.get('tertiaryFixedDim').getDynamicColor(),
|
|
293
|
+
secondBackground: (s) =>
|
|
294
|
+
colorManagerService.get('tertiaryFixed').getDynamicColor(),
|
|
295
|
+
contrastCurve: new ContrastCurve(3, 4.5, 7, 11),
|
|
296
|
+
},
|
|
297
|
+
});
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './main';
|
package/src/main.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { NestFactory } from '@nestjs/core';
|
|
2
|
+
import { AppModule } from './app.module';
|
|
3
|
+
import { AppService } from './app.service';
|
|
4
|
+
|
|
5
|
+
export async function main(): Promise<[AppService, () => Promise<void>]> {
|
|
6
|
+
const app = await NestFactory.create(AppModule);
|
|
7
|
+
const appService = app.get(AppService);
|
|
8
|
+
|
|
9
|
+
const close = () => app.close();
|
|
10
|
+
return [appService, close];
|
|
11
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2023 Google LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { lerp } from '@material/material-color-utilities';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* A class containing a value that changes with the contrast level.
|
|
22
|
+
*
|
|
23
|
+
* Usually represents the contrast requirements for a dynamic color on its
|
|
24
|
+
* background. The four values correspond to values for contrast levels -1.0,
|
|
25
|
+
* 0.0, 0.5, and 1.0, respectively.
|
|
26
|
+
*/
|
|
27
|
+
export class ContrastCurve {
|
|
28
|
+
/**
|
|
29
|
+
* Creates a `ContrastCurve` object.
|
|
30
|
+
*
|
|
31
|
+
* @param low Value for contrast level -1.0
|
|
32
|
+
* @param normal Value for contrast level 0.0
|
|
33
|
+
* @param medium Value for contrast level 0.5
|
|
34
|
+
* @param high Value for contrast level 1.0
|
|
35
|
+
*/
|
|
36
|
+
constructor(
|
|
37
|
+
readonly low: number,
|
|
38
|
+
readonly normal: number,
|
|
39
|
+
readonly medium: number,
|
|
40
|
+
readonly high: number
|
|
41
|
+
) {}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Returns the value at a given contrast level.
|
|
45
|
+
*
|
|
46
|
+
* @param contrastLevel The contrast level. 0.0 is the default (normal); -1.0
|
|
47
|
+
* is the lowest; 1.0 is the highest.
|
|
48
|
+
* @return The value. For contrast ratios, a number between 1.0 and 21.0.
|
|
49
|
+
*/
|
|
50
|
+
get(contrastLevel: number): number {
|
|
51
|
+
if (contrastLevel <= -1.0) {
|
|
52
|
+
return this.low;
|
|
53
|
+
} else if (contrastLevel < 0.0) {
|
|
54
|
+
return lerp(this.low, this.normal, (contrastLevel - -1) / 1);
|
|
55
|
+
} else if (contrastLevel < 0.5) {
|
|
56
|
+
return lerp(this.normal, this.medium, (contrastLevel - 0) / 0.5);
|
|
57
|
+
} else if (contrastLevel < 1.0) {
|
|
58
|
+
return lerp(this.medium, this.high, (contrastLevel - 0.5) / 0.5);
|
|
59
|
+
} else {
|
|
60
|
+
return this.high;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|