@skbkontur/colors 2.0.0-alpha.2 → 2.0.0-alpha.4
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/README.md +104 -171
- package/colors.less +319 -0
- package/colors.scss +319 -0
- package/lib/consts/default-swatch.d.ts +108 -0
- package/lib/consts/default-swatch.js +108 -0
- package/{dist/esm/constants/default-swatch.js → lib/consts/default-swatch.ts} +11 -7
- package/lib/consts/params/abney-correction.d.ts +2 -0
- package/lib/consts/params/abney-correction.js +1102 -0
- package/{dist/cjs/constants/abney-correction.js → lib/consts/params/abney-correction.ts} +3 -4
- package/lib/consts/params/chroma-params.d.ts +2 -0
- package/lib/consts/params/chroma-params.js +102 -0
- package/{dist/esm/constants/chroma-settings.js → lib/consts/params/chroma-params.ts} +3 -1
- package/lib/consts/params/interactions.ts +9 -0
- package/lib/consts/params/logo-lightness.d.ts +1 -0
- package/lib/consts/params/logo-lightness.js +1 -0
- package/lib/consts/params/logo-lightness.ts +1 -0
- package/{dist/cjs/constants → lib/consts/params}/promo-hue-shift.d.ts +1 -1
- package/lib/consts/params/promo-hue-shift.js +11 -0
- package/{dist/esm/constants/promo-hue-shift.js → lib/consts/params/promo-hue-shift.ts} +1 -1
- package/{dist/cjs/constants → lib/consts/params}/warning-hue-patch.d.ts +1 -1
- package/lib/consts/params/warning-hue-patch.js +22 -0
- package/{dist/esm/constants/warning-hue-patch.js → lib/consts/params/warning-hue-patch.ts} +1 -1
- package/lib/get-colors-base.d.ts +11 -0
- package/lib/get-colors-base.js +78 -0
- package/lib/get-colors-base.ts +99 -0
- package/lib/get-colors-default-tokens.d.ts +645 -0
- package/lib/get-colors-default-tokens.js +647 -0
- package/lib/get-colors-default-tokens.ts +646 -0
- package/lib/get-colors.d.ts +40 -0
- package/lib/get-colors.js +28 -0
- package/lib/get-colors.ts +65 -0
- package/{dist/cjs → lib}/helpers/get-interactions.d.ts +2 -2
- package/lib/helpers/get-interactions.js +35 -0
- package/lib/helpers/get-interactions.ts +64 -0
- package/{dist/cjs → lib}/helpers/get-logo.d.ts +2 -2
- package/lib/helpers/get-logo.js +25 -0
- package/lib/helpers/get-logo.ts +40 -0
- package/lib/helpers/get-palette.d.ts +51 -0
- package/lib/helpers/get-palette.js +204 -0
- package/lib/helpers/get-palette.ts +261 -0
- package/lib/helpers/get-promo.d.ts +6 -0
- package/lib/helpers/get-promo.js +47 -0
- package/lib/helpers/get-promo.ts +55 -0
- package/lib/types/tokens-base-generator.d.ts +43 -0
- package/{dist/cjs/types/generator-tokens.d.ts → lib/types/tokens-base-generator.ts} +12 -17
- package/lib/types/tokens-base.d.ts +55 -0
- package/{dist/esm/types/base-tokens.d.ts → lib/types/tokens-base.ts} +7 -2
- package/lib/types/tokens.d.ts +12 -0
- package/lib/types/tokens.js +1 -0
- package/lib/types/tokens.ts +18 -0
- package/lib/utils/convert-color.d.ts +3 -0
- package/lib/utils/convert-color.js +144 -0
- package/lib/utils/convert-color.ts +163 -0
- package/lib/utils/format-variable.js +6 -0
- package/lib/utils/format-variable.ts +7 -0
- package/package.json +44 -19
- package/{dist/tokens → tokens}/brand-blue-deep_accent-brand.css +33 -33
- package/{dist/tokens → tokens}/brand-blue-deep_accent-gray.css +33 -33
- package/{dist/tokens → tokens}/brand-blue_accent-brand.css +33 -33
- package/{dist/tokens → tokens}/brand-blue_accent-gray.css +33 -33
- package/{dist/tokens → tokens}/brand-green_accent-brand.css +33 -33
- package/{dist/tokens → tokens}/brand-green_accent-gray.css +33 -33
- package/{dist/tokens → tokens}/brand-mint_accent-brand.css +33 -33
- package/{dist/tokens → tokens}/brand-mint_accent-gray.css +33 -33
- package/{dist/tokens → tokens}/brand-orange_accent-gray.css +33 -33
- package/{dist/tokens → tokens}/brand-purple_accent-brand.css +33 -33
- package/{dist/tokens → tokens}/brand-purple_accent-gray.css +33 -33
- package/{dist/tokens → tokens}/brand-red_accent-gray.css +33 -33
- package/{dist/tokens → tokens}/brand-violet_accent-brand.css +33 -33
- package/{dist/tokens → tokens}/brand-violet_accent-gray.css +33 -33
- package/tokens-mobile/brand-blue-deep_accent-brand.json +718 -0
- package/tokens-mobile/brand-blue-deep_accent-gray.json +718 -0
- package/tokens-mobile/brand-blue_accent-brand.json +718 -0
- package/tokens-mobile/brand-blue_accent-gray.json +718 -0
- package/tokens-mobile/brand-green_accent-brand.json +718 -0
- package/tokens-mobile/brand-green_accent-gray.json +718 -0
- package/tokens-mobile/brand-mint_accent-brand.json +718 -0
- package/tokens-mobile/brand-mint_accent-gray.json +718 -0
- package/tokens-mobile/brand-orange_accent-gray.json +718 -0
- package/tokens-mobile/brand-purple_accent-brand.json +718 -0
- package/tokens-mobile/brand-purple_accent-gray.json +718 -0
- package/tokens-mobile/brand-red_accent-gray.json +718 -0
- package/tokens-mobile/brand-violet_accent-brand.json +718 -0
- package/tokens-mobile/brand-violet_accent-gray.json +718 -0
- package/dist/cjs/constants/abney-correction.d.ts +0 -2
- package/dist/cjs/constants/chroma-settings.d.ts +0 -2
- package/dist/cjs/constants/chroma-settings.js +0 -105
- package/dist/cjs/constants/default-swatch.d.ts +0 -109
- package/dist/cjs/constants/default-swatch.js +0 -112
- package/dist/cjs/constants/interaction-settings.js +0 -19
- package/dist/cjs/constants/logo-lightness.d.ts +0 -1
- package/dist/cjs/constants/logo-lightness.js +0 -4
- package/dist/cjs/constants/promo-hue-shift.js +0 -14
- package/dist/cjs/constants/warning-hue-patch.js +0 -25
- package/dist/cjs/get-base-tokens.d.ts +0 -26
- package/dist/cjs/get-base-tokens.js +0 -319
- package/dist/cjs/get-colors.d.ts +0 -20
- package/dist/cjs/get-colors.js +0 -20
- package/dist/cjs/get-default-tokens.d.ts +0 -645
- package/dist/cjs/get-default-tokens.js +0 -996
- package/dist/cjs/helpers/get-interactions.js +0 -61
- package/dist/cjs/helpers/get-logo.js +0 -32
- package/dist/cjs/helpers/get-palette.d.ts +0 -76
- package/dist/cjs/helpers/get-palette.js +0 -287
- package/dist/cjs/helpers/get-promo.d.ts +0 -12
- package/dist/cjs/helpers/get-promo.js +0 -56
- package/dist/cjs/types/base-tokens.d.ts +0 -125
- package/dist/cjs/types/base-tokens.js +0 -2
- package/dist/cjs/types/generator-tokens.js +0 -2
- package/dist/cjs/utils/format-variable.js +0 -15
- package/dist/colors.default-dark.js +0 -332
- package/dist/colors.default-light.js +0 -336
- package/dist/colors.less +0 -319
- package/dist/colors.scss +0 -319
- package/dist/esm/constants/abney-correction.d.ts +0 -2
- package/dist/esm/constants/abney-correction.js +0 -1102
- package/dist/esm/constants/chroma-settings.d.ts +0 -2
- package/dist/esm/constants/default-swatch.d.ts +0 -109
- package/dist/esm/constants/interaction-settings.d.ts +0 -8
- package/dist/esm/constants/logo-lightness.d.ts +0 -1
- package/dist/esm/constants/logo-lightness.js +0 -1
- package/dist/esm/constants/promo-hue-shift.d.ts +0 -3
- package/dist/esm/constants/warning-hue-patch.d.ts +0 -3
- package/dist/esm/get-base-tokens.d.ts +0 -26
- package/dist/esm/get-base-tokens.js +0 -257
- package/dist/esm/get-colors.d.ts +0 -20
- package/dist/esm/get-colors.js +0 -16
- package/dist/esm/get-default-tokens.d.ts +0 -645
- package/dist/esm/get-default-tokens.js +0 -992
- package/dist/esm/helpers/get-interactions.d.ts +0 -7
- package/dist/esm/helpers/get-interactions.js +0 -49
- package/dist/esm/helpers/get-logo.d.ts +0 -6
- package/dist/esm/helpers/get-logo.js +0 -28
- package/dist/esm/helpers/get-palette.d.ts +0 -76
- package/dist/esm/helpers/get-palette.js +0 -232
- package/dist/esm/helpers/get-promo.d.ts +0 -12
- package/dist/esm/helpers/get-promo.js +0 -51
- package/dist/esm/types/generator-tokens.d.ts +0 -43
- package/dist/esm/utils/format-variable.d.ts +0 -2
- package/dist/esm/utils/format-variable.js +0 -10
- package/dist/tokens-js/brand-blue-deep_accent-brand.js +0 -644
- package/dist/tokens-js/brand-blue-deep_accent-gray.js +0 -644
- package/dist/tokens-js/brand-blue_accent-brand.js +0 -644
- package/dist/tokens-js/brand-blue_accent-gray.js +0 -644
- package/dist/tokens-js/brand-green_accent-brand.js +0 -644
- package/dist/tokens-js/brand-green_accent-gray.js +0 -644
- package/dist/tokens-js/brand-mint_accent-brand.js +0 -644
- package/dist/tokens-js/brand-mint_accent-gray.js +0 -644
- package/dist/tokens-js/brand-orange_accent-gray.js +0 -644
- package/dist/tokens-js/brand-purple_accent-brand.js +0 -644
- package/dist/tokens-js/brand-purple_accent-gray.js +0 -644
- package/dist/tokens-js/brand-red_accent-gray.js +0 -644
- package/dist/tokens-js/brand-violet_accent-brand.js +0 -644
- package/dist/tokens-js/brand-violet_accent-gray.js +0 -644
- package/dist/tokens-mobile/brand-blue-deep_accent-brand.json +0 -718
- package/dist/tokens-mobile/brand-blue-deep_accent-gray.json +0 -718
- package/dist/tokens-mobile/brand-blue_accent-brand.json +0 -718
- package/dist/tokens-mobile/brand-blue_accent-gray.json +0 -718
- package/dist/tokens-mobile/brand-green_accent-brand.json +0 -718
- package/dist/tokens-mobile/brand-green_accent-gray.json +0 -718
- package/dist/tokens-mobile/brand-mint_accent-brand.json +0 -718
- package/dist/tokens-mobile/brand-mint_accent-gray.json +0 -718
- package/dist/tokens-mobile/brand-orange_accent-gray.json +0 -718
- package/dist/tokens-mobile/brand-purple_accent-brand.json +0 -718
- package/dist/tokens-mobile/brand-purple_accent-gray.json +0 -718
- package/dist/tokens-mobile/brand-red_accent-gray.json +0 -718
- package/dist/tokens-mobile/brand-violet_accent-brand.json +0 -718
- package/dist/tokens-mobile/brand-violet_accent-gray.json +0 -718
- /package/{dist/colors.js → colors.js} +0 -0
- /package/{dist/cjs/constants/interaction-settings.d.ts → lib/consts/params/interactions.d.ts} +0 -0
- /package/{dist/esm/constants/interaction-settings.js → lib/consts/params/interactions.js} +0 -0
- /package/{dist/esm/types/base-tokens.js → lib/types/tokens-base-generator.js} +0 -0
- /package/{dist/esm/types/generator-tokens.js → lib/types/tokens-base.js} +0 -0
- /package/{dist/cjs → lib}/utils/format-variable.d.ts +0 -0
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { clampChroma, converter } from 'culori';
|
|
2
|
+
import { calcAPCA } from 'apca-w3';
|
|
3
|
+
|
|
4
|
+
import type {
|
|
5
|
+
GeneratorColorAbneyCorrection,
|
|
6
|
+
GeneratorColorChromaParamsGroup,
|
|
7
|
+
GeneratorColorPalette,
|
|
8
|
+
GeneratorColorWarningHuePatch,
|
|
9
|
+
} from '../types/tokens-base-generator.js';
|
|
10
|
+
import * as DefaultSwatch from '../consts/default-swatch.js';
|
|
11
|
+
import { CHROMA_PARAMS } from '../consts/params/chroma-params.js';
|
|
12
|
+
import { ABNEY_CORRECTION } from '../consts/params/abney-correction.js';
|
|
13
|
+
import { PROMO_HUE_SHIFTS } from '../consts/params/promo-hue-shift.js';
|
|
14
|
+
import { WARNING_HUE_PATCH } from '../consts/params/warning-hue-patch.js';
|
|
15
|
+
|
|
16
|
+
interface GeneratePaletteParams {
|
|
17
|
+
color: string;
|
|
18
|
+
type?: 'default' | 'warning';
|
|
19
|
+
settings?: {
|
|
20
|
+
chromaSettings?: GeneratorColorChromaParamsGroup;
|
|
21
|
+
abneyCorrection?: GeneratorColorAbneyCorrection;
|
|
22
|
+
promoHueShifts?: { [hueRange: number]: number };
|
|
23
|
+
warningHuePatch?: GeneratorColorWarningHuePatch;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function getPalette({
|
|
28
|
+
color,
|
|
29
|
+
type = 'default',
|
|
30
|
+
settings: customSettings,
|
|
31
|
+
}: GeneratePaletteParams): GeneratorColorPalette {
|
|
32
|
+
const defaultSettings = {
|
|
33
|
+
chromaSettings: CHROMA_PARAMS,
|
|
34
|
+
abneyCorrection: ABNEY_CORRECTION,
|
|
35
|
+
promoHueShifts: PROMO_HUE_SHIFTS,
|
|
36
|
+
warningHuePatch: WARNING_HUE_PATCH,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const settings = {
|
|
40
|
+
...defaultSettings,
|
|
41
|
+
...customSettings,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const toOklch = converter('oklch');
|
|
45
|
+
const oklchColor = toOklch(color);
|
|
46
|
+
const currentHue = oklchColor?.h || 0;
|
|
47
|
+
|
|
48
|
+
const toNorm = (x: number) => x / 100;
|
|
49
|
+
|
|
50
|
+
const calculateChromaValue = (
|
|
51
|
+
rel: number,
|
|
52
|
+
min: number | undefined,
|
|
53
|
+
max: number | undefined,
|
|
54
|
+
baseChromaMax: number
|
|
55
|
+
) => {
|
|
56
|
+
const raw = (baseChromaMax * rel) / 100;
|
|
57
|
+
let value = raw;
|
|
58
|
+
if (min !== undefined) {
|
|
59
|
+
value = Math.max(toNorm(min), value);
|
|
60
|
+
}
|
|
61
|
+
if (max !== undefined) {
|
|
62
|
+
value = Math.min(toNorm(max), value);
|
|
63
|
+
}
|
|
64
|
+
return Math.min(value, baseChromaMax);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const result: GeneratorColorPalette = {
|
|
68
|
+
vivid: {},
|
|
69
|
+
normal: {},
|
|
70
|
+
dim: {},
|
|
71
|
+
};
|
|
72
|
+
const isWarning = type === 'warning';
|
|
73
|
+
|
|
74
|
+
for (const Lstr in settings.chromaSettings) {
|
|
75
|
+
const L = +Lstr;
|
|
76
|
+
if (L === 100) {
|
|
77
|
+
result.vivid[L] = `oklch(100% 0 0)`;
|
|
78
|
+
result.normal[L] = `oklch(100% 0 0)`;
|
|
79
|
+
result.dim[L] = `oklch(100% 0 0)`;
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const hueAfterWarningPatch = applyWarningHuePatch(currentHue, L, settings.warningHuePatch, isWarning);
|
|
84
|
+
const appliedHueShift = applyAbneyShift(L, hueAfterWarningPatch, settings.abneyCorrection);
|
|
85
|
+
|
|
86
|
+
const chromaMax = clampChroma({ mode: 'oklch', l: L / 100, c: 1, h: appliedHueShift }, 'oklch').c;
|
|
87
|
+
const currentParams = settings.chromaSettings[L];
|
|
88
|
+
|
|
89
|
+
const vividN = calculateChromaValue(
|
|
90
|
+
currentParams.vivid.rel,
|
|
91
|
+
currentParams.vivid.min,
|
|
92
|
+
currentParams.vivid.max,
|
|
93
|
+
chromaMax
|
|
94
|
+
);
|
|
95
|
+
const normN = calculateChromaValue(
|
|
96
|
+
currentParams.normal.rel,
|
|
97
|
+
currentParams.normal.min,
|
|
98
|
+
currentParams.normal.max,
|
|
99
|
+
chromaMax
|
|
100
|
+
);
|
|
101
|
+
const dimN = calculateChromaValue(currentParams.dim.rel, currentParams.dim.min, currentParams.dim.max, chromaMax);
|
|
102
|
+
|
|
103
|
+
result.vivid[L] = `oklch(${L}% ${vividN.toFixed(3)} ${appliedHueShift.toFixed(0)})`;
|
|
104
|
+
result.normal[L] = `oklch(${L}% ${normN.toFixed(3)} ${appliedHueShift.toFixed(0)})`;
|
|
105
|
+
result.dim[L] = `oklch(${L}% ${dimN.toFixed(3)} ${appliedHueShift.toFixed(0)})`;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function getAbneyHueShift(
|
|
112
|
+
lightness: number,
|
|
113
|
+
currentHue: number,
|
|
114
|
+
abneyData: GeneratorColorAbneyCorrection
|
|
115
|
+
): number {
|
|
116
|
+
const lightnessData = abneyData[lightness];
|
|
117
|
+
if (!lightnessData) {
|
|
118
|
+
return 0;
|
|
119
|
+
}
|
|
120
|
+
const hueRanges = Object.keys(lightnessData)
|
|
121
|
+
.map(Number)
|
|
122
|
+
.sort((a, b) => a - b);
|
|
123
|
+
let selectedHueRange = hueRanges[0];
|
|
124
|
+
for (let i = 0; i < hueRanges.length; i++) {
|
|
125
|
+
const startRange = hueRanges[i];
|
|
126
|
+
const endRange = hueRanges[i + 1] !== undefined ? hueRanges[i + 1] : 360;
|
|
127
|
+
if (currentHue >= startRange && currentHue < endRange) {
|
|
128
|
+
selectedHueRange = startRange;
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
if (i === hueRanges.length - 1 && currentHue >= startRange && currentHue < 360) {
|
|
132
|
+
selectedHueRange = startRange;
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return lightnessData[selectedHueRange] !== undefined ? lightnessData[selectedHueRange] : 0;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function applyAbneyShift(
|
|
140
|
+
lightness: number,
|
|
141
|
+
currentHue: number,
|
|
142
|
+
abneyData: GeneratorColorAbneyCorrection
|
|
143
|
+
): number {
|
|
144
|
+
const abneyShift = getAbneyHueShift(lightness, currentHue, abneyData);
|
|
145
|
+
return (currentHue + abneyShift + 360) % 360;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function applyWarningHuePatch(
|
|
149
|
+
currentHue: number,
|
|
150
|
+
lightness: number,
|
|
151
|
+
warningHuePatchData: GeneratorColorWarningHuePatch,
|
|
152
|
+
isWarningMode: boolean
|
|
153
|
+
): number {
|
|
154
|
+
if (isWarningMode) {
|
|
155
|
+
const patch = warningHuePatchData[lightness];
|
|
156
|
+
if (patch !== undefined) {
|
|
157
|
+
return (currentHue + patch + 360) % 360;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return currentHue;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function findClosestLightnessStep(targetL: number, availableLightnessSteps: number[]): number {
|
|
164
|
+
if (availableLightnessSteps.length === 0) {
|
|
165
|
+
return targetL;
|
|
166
|
+
}
|
|
167
|
+
const sortedSteps = [...availableLightnessSteps].sort((a, b) => a - b);
|
|
168
|
+
let closestStep = sortedSteps[0];
|
|
169
|
+
let minDiff = Math.abs(targetL - closestStep);
|
|
170
|
+
for (let i = 1; i < sortedSteps.length; i++) {
|
|
171
|
+
const currentStep = sortedSteps[i];
|
|
172
|
+
const diff = Math.abs(targetL - currentStep);
|
|
173
|
+
if (diff < minDiff || (diff === minDiff && currentStep > closestStep)) {
|
|
174
|
+
minDiff = diff;
|
|
175
|
+
closestStep = currentStep;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return closestStep;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export function calculateBaseHueAndCorrectionRange(
|
|
182
|
+
inputColorString: string,
|
|
183
|
+
abneyData: GeneratorColorAbneyCorrection
|
|
184
|
+
): {
|
|
185
|
+
baseHue: number;
|
|
186
|
+
correctionLightness: number;
|
|
187
|
+
correctionHueRange: number;
|
|
188
|
+
} | null {
|
|
189
|
+
const toOklch = converter('oklch');
|
|
190
|
+
const oklch = toOklch(inputColorString) as { l: number; c: number; h: number };
|
|
191
|
+
if (!oklch) {
|
|
192
|
+
console.warn(`Could not parse color string: ${inputColorString}`);
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
const targetLightness = Math.round(oklch.l * 100);
|
|
196
|
+
let targetHue = oklch.h;
|
|
197
|
+
if (isNaN(targetHue)) {
|
|
198
|
+
console.warn(`Achromatic color detected (${inputColorString}). Defaulting hue to 0.`);
|
|
199
|
+
targetHue = 0;
|
|
200
|
+
}
|
|
201
|
+
const availableLightnessSteps = Object.keys(abneyData).map(Number);
|
|
202
|
+
if (availableLightnessSteps.length === 0) {
|
|
203
|
+
console.warn('Abney correction data is empty, cannot calculate base hue.');
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
const closestLightness = findClosestLightnessStep(targetLightness, availableLightnessSteps);
|
|
207
|
+
const lightnessCorrectionData = abneyData[closestLightness];
|
|
208
|
+
if (!lightnessCorrectionData) {
|
|
209
|
+
console.warn(`No Abney correction data for lightness ${closestLightness}.`);
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
const correctedHueMap = Object.entries(lightnessCorrectionData).map(([rawHueStr, shift]) => {
|
|
213
|
+
const rawHue = Number(rawHueStr);
|
|
214
|
+
return {
|
|
215
|
+
rawHue,
|
|
216
|
+
shift,
|
|
217
|
+
correctedHue: (rawHue + shift + 360) % 360,
|
|
218
|
+
};
|
|
219
|
+
});
|
|
220
|
+
correctedHueMap.sort((a, b) => {
|
|
221
|
+
if (a.correctedHue !== b.correctedHue) {
|
|
222
|
+
return a.correctedHue - b.correctedHue;
|
|
223
|
+
}
|
|
224
|
+
return a.rawHue - b.rawHue;
|
|
225
|
+
});
|
|
226
|
+
if (correctedHueMap.length === 0) {
|
|
227
|
+
console.warn(`No hue ranges defined for lightness ${closestLightness}.`);
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
const findCorrectRange = () => {
|
|
231
|
+
const nextRangeIndex = correctedHueMap.findIndex((range) => range.correctedHue > targetHue);
|
|
232
|
+
if (nextRangeIndex === 0) {
|
|
233
|
+
return correctedHueMap[correctedHueMap.length - 1];
|
|
234
|
+
}
|
|
235
|
+
if (nextRangeIndex > 0) {
|
|
236
|
+
return correctedHueMap[nextRangeIndex - 1];
|
|
237
|
+
}
|
|
238
|
+
return correctedHueMap[correctedHueMap.length - 1];
|
|
239
|
+
};
|
|
240
|
+
const selectedRange = findCorrectRange();
|
|
241
|
+
if (!selectedRange) {
|
|
242
|
+
console.error('Could not determine the correct hue range.');
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
const baseHue = (targetHue - selectedRange.shift + 360) % 360;
|
|
246
|
+
return {
|
|
247
|
+
baseHue,
|
|
248
|
+
correctionLightness: closestLightness,
|
|
249
|
+
correctionHueRange: selectedRange.rawHue,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export function calcOnBrand(hex: string) {
|
|
254
|
+
const whiteContrast = Math.abs(Number(calcAPCA('#fff', hex)));
|
|
255
|
+
const blackContrast = Math.abs(Number(calcAPCA('#000', hex)));
|
|
256
|
+
|
|
257
|
+
if (whiteContrast + 10 >= blackContrast) {
|
|
258
|
+
return DefaultSwatch.whiteAlpha;
|
|
259
|
+
}
|
|
260
|
+
return DefaultSwatch.blackAlpha;
|
|
261
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { clampChroma, converter, formatHex } from 'culori';
|
|
2
|
+
import { PROMO_HUE_SHIFTS } from '../consts/params/promo-hue-shift.js';
|
|
3
|
+
export function getPromo(color, hueShifts) {
|
|
4
|
+
if (hueShifts === void 0) { hueShifts = PROMO_HUE_SHIFTS; }
|
|
5
|
+
var toOklch = converter('oklch');
|
|
6
|
+
var oklchColor = toOklch(color);
|
|
7
|
+
if (!oklchColor) {
|
|
8
|
+
throw new Error("Invalid color string: ".concat(color));
|
|
9
|
+
}
|
|
10
|
+
var currentHue = oklchColor.h;
|
|
11
|
+
var promoHueShift = getPromoHueShift(currentHue, hueShifts);
|
|
12
|
+
var correctedHue = (currentHue + promoHueShift + 360) % 360;
|
|
13
|
+
var promoLightness = oklchColor.l * 100;
|
|
14
|
+
if (promoLightness >= 50) {
|
|
15
|
+
promoLightness = promoLightness - 32;
|
|
16
|
+
}
|
|
17
|
+
promoLightness = Math.min(Math.max(promoLightness, 30), 34);
|
|
18
|
+
var promoChroma = 0.1;
|
|
19
|
+
var finalLightness = Math.round(promoLightness) / 100;
|
|
20
|
+
var finalChroma = Math.round(promoChroma * 100) / 100;
|
|
21
|
+
var promoOklch = {
|
|
22
|
+
mode: 'oklch',
|
|
23
|
+
l: finalLightness,
|
|
24
|
+
c: finalChroma,
|
|
25
|
+
h: correctedHue,
|
|
26
|
+
};
|
|
27
|
+
return formatHex(clampChroma(promoOklch, 'oklch'));
|
|
28
|
+
}
|
|
29
|
+
export function getPromoHueShift(currentHue, promoHueShifts) {
|
|
30
|
+
var hueRanges = Object.keys(promoHueShifts)
|
|
31
|
+
.map(Number)
|
|
32
|
+
.sort(function (a, b) { return a - b; });
|
|
33
|
+
var selectedHueRange = hueRanges[0];
|
|
34
|
+
for (var i = 0; i < hueRanges.length; i++) {
|
|
35
|
+
var startRange = hueRanges[i];
|
|
36
|
+
var endRange = hueRanges[i + 1] !== undefined ? hueRanges[i + 1] : 360;
|
|
37
|
+
if (currentHue >= startRange && currentHue < endRange) {
|
|
38
|
+
selectedHueRange = startRange;
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
if (i === hueRanges.length - 1 && (currentHue >= startRange || currentHue < hueRanges[0])) {
|
|
42
|
+
selectedHueRange = startRange;
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return promoHueShifts[selectedHueRange] !== undefined ? promoHueShifts[selectedHueRange] : 0;
|
|
47
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { clampChroma, converter, formatHex, type Oklch } from 'culori';
|
|
2
|
+
|
|
3
|
+
import { PROMO_HUE_SHIFTS } from '../consts/params/promo-hue-shift.js';
|
|
4
|
+
|
|
5
|
+
export function getPromo(color: string, hueShifts = PROMO_HUE_SHIFTS): string {
|
|
6
|
+
const toOklch = converter('oklch');
|
|
7
|
+
const oklchColor = toOklch(color) as Oklch;
|
|
8
|
+
if (!oklchColor) {
|
|
9
|
+
throw new Error(`Invalid color string: ${color}`);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const currentHue = oklchColor.h as number;
|
|
13
|
+
const promoHueShift = getPromoHueShift(currentHue, hueShifts);
|
|
14
|
+
const correctedHue = (currentHue + promoHueShift + 360) % 360;
|
|
15
|
+
|
|
16
|
+
let promoLightness = oklchColor.l * 100;
|
|
17
|
+
if (promoLightness >= 50) {
|
|
18
|
+
promoLightness = promoLightness - 32;
|
|
19
|
+
}
|
|
20
|
+
promoLightness = Math.min(Math.max(promoLightness, 30), 34);
|
|
21
|
+
|
|
22
|
+
const promoChroma = 0.1;
|
|
23
|
+
|
|
24
|
+
const finalLightness = Math.round(promoLightness) / 100;
|
|
25
|
+
const finalChroma = Math.round(promoChroma * 100) / 100;
|
|
26
|
+
|
|
27
|
+
const promoOklch: Oklch = {
|
|
28
|
+
mode: 'oklch',
|
|
29
|
+
l: finalLightness,
|
|
30
|
+
c: finalChroma,
|
|
31
|
+
h: correctedHue,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
return formatHex(clampChroma(promoOklch, 'oklch'));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function getPromoHueShift(currentHue: number, promoHueShifts: { [hueRange: number]: number }): number {
|
|
38
|
+
const hueRanges = Object.keys(promoHueShifts)
|
|
39
|
+
.map(Number)
|
|
40
|
+
.sort((a, b) => a - b);
|
|
41
|
+
let selectedHueRange = hueRanges[0];
|
|
42
|
+
for (let i = 0; i < hueRanges.length; i++) {
|
|
43
|
+
const startRange = hueRanges[i];
|
|
44
|
+
const endRange = hueRanges[i + 1] !== undefined ? hueRanges[i + 1] : 360;
|
|
45
|
+
if (currentHue >= startRange && currentHue < endRange) {
|
|
46
|
+
selectedHueRange = startRange;
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
if (i === hueRanges.length - 1 && (currentHue >= startRange || currentHue < hueRanges[0])) {
|
|
50
|
+
selectedHueRange = startRange;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return promoHueShifts[selectedHueRange] !== undefined ? promoHueShifts[selectedHueRange] : 0;
|
|
55
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface GeneratorColorChromaParamsGroup {
|
|
2
|
+
[key: number]: {
|
|
3
|
+
vivid: GeneratorColorChromaSettings;
|
|
4
|
+
normal: GeneratorColorChromaSettings;
|
|
5
|
+
dim: GeneratorColorChromaSettings;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
export interface GeneratorColorChromaSettings {
|
|
9
|
+
rel: number;
|
|
10
|
+
min?: number;
|
|
11
|
+
max?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface GeneratorColorPalette {
|
|
14
|
+
vivid: {
|
|
15
|
+
[key: number]: string;
|
|
16
|
+
};
|
|
17
|
+
normal: {
|
|
18
|
+
[key: number]: string;
|
|
19
|
+
};
|
|
20
|
+
dim: {
|
|
21
|
+
[key: number]: string;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export interface GeneratorColorAbneyCorrection {
|
|
25
|
+
[lightness: number]: {
|
|
26
|
+
[hueShiftRange: number]: number;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export interface GeneratorColorWarningHuePatch {
|
|
30
|
+
[lightness: number]: number;
|
|
31
|
+
}
|
|
32
|
+
export interface GeneratorPaletteParams {
|
|
33
|
+
color: string;
|
|
34
|
+
type?: 'default' | 'warning' | 'promo';
|
|
35
|
+
settings?: {
|
|
36
|
+
chromaSettings?: GeneratorColorChromaParamsGroup;
|
|
37
|
+
abneyCorrection?: GeneratorColorAbneyCorrection;
|
|
38
|
+
promoHueShifts?: {
|
|
39
|
+
[hueRange: number]: number;
|
|
40
|
+
};
|
|
41
|
+
warningHuePatch?: GeneratorColorWarningHuePatch;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -1,43 +1,38 @@
|
|
|
1
|
-
export interface
|
|
1
|
+
export interface GeneratorColorChromaParamsGroup {
|
|
2
2
|
[key: number]: {
|
|
3
3
|
vivid: GeneratorColorChromaSettings;
|
|
4
4
|
normal: GeneratorColorChromaSettings;
|
|
5
5
|
dim: GeneratorColorChromaSettings;
|
|
6
6
|
};
|
|
7
7
|
}
|
|
8
|
+
|
|
8
9
|
export interface GeneratorColorChromaSettings {
|
|
9
10
|
rel: number;
|
|
10
11
|
min?: number;
|
|
11
12
|
max?: number;
|
|
12
13
|
}
|
|
14
|
+
|
|
13
15
|
export interface GeneratorColorPalette {
|
|
14
|
-
vivid: {
|
|
15
|
-
|
|
16
|
-
};
|
|
17
|
-
normal: {
|
|
18
|
-
[key: number]: string;
|
|
19
|
-
};
|
|
20
|
-
dim: {
|
|
21
|
-
[key: number]: string;
|
|
22
|
-
};
|
|
16
|
+
vivid: { [key: number]: string };
|
|
17
|
+
normal: { [key: number]: string };
|
|
18
|
+
dim: { [key: number]: string };
|
|
23
19
|
}
|
|
20
|
+
|
|
24
21
|
export interface GeneratorColorAbneyCorrection {
|
|
25
|
-
[lightness: number]: {
|
|
26
|
-
[hueShiftRange: number]: number;
|
|
27
|
-
};
|
|
22
|
+
[lightness: number]: { [hueShiftRange: number]: number };
|
|
28
23
|
}
|
|
24
|
+
|
|
29
25
|
export interface GeneratorColorWarningHuePatch {
|
|
30
26
|
[lightness: number]: number;
|
|
31
27
|
}
|
|
28
|
+
|
|
32
29
|
export interface GeneratorPaletteParams {
|
|
33
30
|
color: string;
|
|
34
31
|
type?: 'default' | 'warning' | 'promo';
|
|
35
32
|
settings?: {
|
|
36
|
-
chromaSettings?:
|
|
33
|
+
chromaSettings?: GeneratorColorChromaParamsGroup;
|
|
37
34
|
abneyCorrection?: GeneratorColorAbneyCorrection;
|
|
38
|
-
promoHueShifts?: {
|
|
39
|
-
[hueRange: number]: number;
|
|
40
|
-
};
|
|
35
|
+
promoHueShifts?: { [hueRange: number]: number };
|
|
41
36
|
warningHuePatch?: GeneratorColorWarningHuePatch;
|
|
42
37
|
};
|
|
43
38
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export interface TokensBase {
|
|
2
|
+
brand: {
|
|
3
|
+
logo: ThemedValue;
|
|
4
|
+
original: string;
|
|
5
|
+
promo: string;
|
|
6
|
+
interactions: {
|
|
7
|
+
hover: ThemedValue;
|
|
8
|
+
pressed: ThemedValue;
|
|
9
|
+
};
|
|
10
|
+
palette: ColorPalette;
|
|
11
|
+
};
|
|
12
|
+
accent?: {
|
|
13
|
+
original: ThemedValue;
|
|
14
|
+
interactions: {
|
|
15
|
+
hover: ThemedValue;
|
|
16
|
+
pressed: ThemedValue;
|
|
17
|
+
};
|
|
18
|
+
palette?: ColorPalette;
|
|
19
|
+
};
|
|
20
|
+
warning: ColorPalette;
|
|
21
|
+
error: ColorPalette;
|
|
22
|
+
success: ColorPalette;
|
|
23
|
+
gray: ColorWithScale<GrayScale>;
|
|
24
|
+
whiteAlpha: ColorWithScale<AlphaScale>;
|
|
25
|
+
blackAlpha: ColorWithScale<AlphaScale>;
|
|
26
|
+
onBrand: ColorWithScale<AlphaScale>;
|
|
27
|
+
onAccent?: ColorWithScale<AlphaScale>;
|
|
28
|
+
customizable: {
|
|
29
|
+
red: ColorPalette;
|
|
30
|
+
orange: ColorPalette;
|
|
31
|
+
green: ColorPalette;
|
|
32
|
+
mint: ColorPalette;
|
|
33
|
+
blue: ColorPalette;
|
|
34
|
+
blueDeep: ColorPalette;
|
|
35
|
+
violet: ColorPalette;
|
|
36
|
+
purple: ColorPalette;
|
|
37
|
+
yellow: ColorPalette;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export interface ColorPalette {
|
|
41
|
+
vivid: ColorWithScale<ChromaScale>;
|
|
42
|
+
normal: ColorWithScale<ChromaScale>;
|
|
43
|
+
dim: ColorWithScale<ChromaScale>;
|
|
44
|
+
}
|
|
45
|
+
export type ChromaScale = 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | 96;
|
|
46
|
+
type AlphaScale = 4 | 6 | 8 | 12 | 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | 96 | 100;
|
|
47
|
+
export type GrayScale = 0 | 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | 96 | 98 | 100;
|
|
48
|
+
type ColorWithScale<T extends string | number> = {
|
|
49
|
+
[K in T]: string;
|
|
50
|
+
};
|
|
51
|
+
export interface ThemedValue {
|
|
52
|
+
light: string;
|
|
53
|
+
dark: string;
|
|
54
|
+
}
|
|
55
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export interface
|
|
1
|
+
export interface TokensBase {
|
|
2
2
|
brand: {
|
|
3
3
|
logo: ThemedValue;
|
|
4
4
|
original: string;
|
|
@@ -37,11 +37,13 @@ export interface BaseTokens {
|
|
|
37
37
|
yellow: ColorPalette;
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
|
+
|
|
40
41
|
export interface ColorPalette {
|
|
41
42
|
vivid: ColorWithScale<ChromaScale>;
|
|
42
43
|
normal: ColorWithScale<ChromaScale>;
|
|
43
44
|
dim: ColorWithScale<ChromaScale>;
|
|
44
45
|
}
|
|
46
|
+
|
|
45
47
|
export type ChromaScale =
|
|
46
48
|
| 20
|
|
47
49
|
| 24
|
|
@@ -63,6 +65,7 @@ export type ChromaScale =
|
|
|
63
65
|
| 88
|
|
64
66
|
| 92
|
|
65
67
|
| 96;
|
|
68
|
+
|
|
66
69
|
type AlphaScale =
|
|
67
70
|
| 4
|
|
68
71
|
| 6
|
|
@@ -90,6 +93,7 @@ type AlphaScale =
|
|
|
90
93
|
| 92
|
|
91
94
|
| 96
|
|
92
95
|
| 100;
|
|
96
|
+
|
|
93
97
|
export type GrayScale =
|
|
94
98
|
| 0
|
|
95
99
|
| 16
|
|
@@ -115,11 +119,12 @@ export type GrayScale =
|
|
|
115
119
|
| 96
|
|
116
120
|
| 98
|
|
117
121
|
| 100;
|
|
122
|
+
|
|
118
123
|
type ColorWithScale<T extends string | number> = {
|
|
119
124
|
[K in T]: string;
|
|
120
125
|
};
|
|
126
|
+
|
|
121
127
|
export interface ThemedValue {
|
|
122
128
|
light: string;
|
|
123
129
|
dark: string;
|
|
124
130
|
}
|
|
125
|
-
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { getColorsDefaultTokens } from '../get-colors-default-tokens.js';
|
|
2
|
+
export interface Themed<T> {
|
|
3
|
+
light: T;
|
|
4
|
+
dark: T;
|
|
5
|
+
}
|
|
6
|
+
export interface ColorObject {
|
|
7
|
+
[key: string]: ColorValue;
|
|
8
|
+
}
|
|
9
|
+
export type ColorValue = string | ColorObject | ColorValue[];
|
|
10
|
+
export type ColorStructure = ColorObject | ColorValue[];
|
|
11
|
+
export type DefaultTokensFull = ReturnType<typeof getColorsDefaultTokens>;
|
|
12
|
+
export type DefaultTokens = DefaultTokensFull | DefaultTokensFull['light' | 'dark'];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { getColorsDefaultTokens } from '../get-colors-default-tokens.js';
|
|
2
|
+
|
|
3
|
+
export interface Themed<T> {
|
|
4
|
+
light: T;
|
|
5
|
+
dark: T;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface ColorObject {
|
|
9
|
+
[key: string]: ColorValue;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type ColorValue = string | ColorObject | ColorValue[];
|
|
13
|
+
|
|
14
|
+
export type ColorStructure = ColorObject | ColorValue[];
|
|
15
|
+
|
|
16
|
+
export type DefaultTokensFull = ReturnType<typeof getColorsDefaultTokens>;
|
|
17
|
+
|
|
18
|
+
export type DefaultTokens = DefaultTokensFull | DefaultTokensFull['light' | 'dark'];
|