@ankhorage/zora 0.12.2 → 0.13.1
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 +18 -0
- package/dist/internal/color/colorToneRecipes.d.ts +23 -0
- package/dist/internal/color/colorToneRecipes.d.ts.map +1 -0
- package/dist/internal/color/colorToneRecipes.js +139 -0
- package/dist/internal/color/colorToneRecipes.js.map +1 -0
- package/dist/internal/color/index.d.ts +3 -1
- package/dist/internal/color/index.d.ts.map +1 -1
- package/dist/internal/color/index.js +2 -0
- package/dist/internal/color/index.js.map +1 -1
- package/dist/internal/color/roleScales.d.ts +20 -0
- package/dist/internal/color/roleScales.d.ts.map +1 -0
- package/dist/internal/color/roleScales.js +79 -0
- package/dist/internal/color/roleScales.js.map +1 -0
- package/dist/internal/color/scales.d.ts +9 -0
- package/dist/internal/color/scales.d.ts.map +1 -1
- package/dist/internal/color/scales.js +25 -0
- package/dist/internal/color/scales.js.map +1 -1
- package/dist/theme/createZoraThemeConfig.js +2 -2
- package/dist/theme/createZoraThemeConfig.js.map +1 -1
- package/dist/theme/types.d.ts +6 -4
- package/dist/theme/types.d.ts.map +1 -1
- package/dist/theme/types.js +20 -1
- package/dist/theme/types.js.map +1 -1
- package/dist/theme/zoraDefaultTheme.js +1 -1
- package/dist/theme/zoraDefaultTheme.js.map +1 -1
- package/package.json +2 -2
- package/src/internal/color/colorToneRecipes.test.ts +89 -0
- package/src/internal/color/colorToneRecipes.ts +167 -0
- package/src/internal/color/index.ts +17 -0
- package/src/internal/color/roleHues.test.ts +1 -1
- package/src/internal/color/roleScales.test.ts +220 -0
- package/src/internal/color/roleScales.ts +127 -0
- package/src/internal/color/scales.ts +49 -0
- package/src/theme/createZoraThemeConfig.test.ts +5 -5
- package/src/theme/createZoraThemeConfig.ts +2 -2
- package/src/theme/types.ts +26 -10
- package/src/theme/zoraDefaultTheme.ts +1 -1
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { ZoraHexColor } from '../../theme/types';
|
|
2
|
+
import type { ZoraColorToneRecipe } from './colorToneRecipes';
|
|
3
|
+
import { getZoraColorToneRoleChromaFactor } from './colorToneRecipes';
|
|
2
4
|
import { clampOklchToGamut, formatOklchAsHex, parseHexToOklch } from './oklch';
|
|
3
5
|
import { type ZoraColorScale, type ZoraColorScaleStep } from './types';
|
|
4
6
|
|
|
@@ -7,6 +9,15 @@ export interface CreateZoraColorScaleOptions {
|
|
|
7
9
|
role?: 'primary' | 'neutral';
|
|
8
10
|
}
|
|
9
11
|
|
|
12
|
+
export type ZoraHueScaleRoleId = 'primary' | 'secondary' | 'accent' | 'highlight' | 'surfaceTint';
|
|
13
|
+
|
|
14
|
+
export interface CreateZoraHueScaleOptions {
|
|
15
|
+
hue: number;
|
|
16
|
+
seedChroma: number;
|
|
17
|
+
role: ZoraHueScaleRoleId;
|
|
18
|
+
colorToneRecipe: ZoraColorToneRecipe;
|
|
19
|
+
}
|
|
20
|
+
|
|
10
21
|
const PRIMARY_LIGHTNESS_BY_STEP: Record<ZoraColorScaleStep, number> = {
|
|
11
22
|
50: 0.97,
|
|
12
23
|
100: 0.93,
|
|
@@ -69,6 +80,36 @@ function resolvePrimaryScaleChroma(seedChroma: number, step: ZoraColorScaleStep)
|
|
|
69
80
|
return shouldEnforceMin ? Math.max(bounded, MIN_PRIMARY_SCALE_CHROMA) : bounded;
|
|
70
81
|
}
|
|
71
82
|
|
|
83
|
+
function resolveRoleScaleChroma(options: {
|
|
84
|
+
seedChroma: number;
|
|
85
|
+
step: ZoraColorScaleStep;
|
|
86
|
+
maxChroma: number;
|
|
87
|
+
minMidChroma: number;
|
|
88
|
+
}): number {
|
|
89
|
+
const cappedSeedChroma = clampNumber(options.seedChroma, 0, options.maxChroma);
|
|
90
|
+
const multiplier = PRIMARY_CHROMA_MULTIPLIER_BY_STEP[options.step];
|
|
91
|
+
const scaled = cappedSeedChroma * multiplier;
|
|
92
|
+
const bounded = clampNumber(scaled, 0, options.maxChroma);
|
|
93
|
+
const shouldEnforceMin =
|
|
94
|
+
options.step >= 300 && options.step <= 700 && options.seedChroma >= options.minMidChroma;
|
|
95
|
+
|
|
96
|
+
return shouldEnforceMin ? Math.max(bounded, options.minMidChroma) : bounded;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function resolveHueScaleChroma(
|
|
100
|
+
options: CreateZoraHueScaleOptions,
|
|
101
|
+
step: ZoraColorScaleStep,
|
|
102
|
+
): number {
|
|
103
|
+
const factor = getZoraColorToneRoleChromaFactor(options.colorToneRecipe, options.role);
|
|
104
|
+
|
|
105
|
+
return resolveRoleScaleChroma({
|
|
106
|
+
seedChroma: options.seedChroma * factor,
|
|
107
|
+
step,
|
|
108
|
+
maxChroma: options.colorToneRecipe.maxChroma,
|
|
109
|
+
minMidChroma: options.colorToneRecipe.minMidChroma,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
72
113
|
function createScaleEntries(options: CreateZoraColorScaleOptions): ZoraColorScale {
|
|
73
114
|
const seed = parseHexToOklch(options.seed);
|
|
74
115
|
|
|
@@ -143,3 +184,11 @@ export function createZoraPrimaryScale(seed: ZoraHexColor): ZoraColorScale {
|
|
|
143
184
|
export function createZoraNeutralScale(seed: ZoraHexColor = '#94a3b8'): ZoraColorScale {
|
|
144
185
|
return createZoraColorScale({ seed, role: 'neutral' });
|
|
145
186
|
}
|
|
187
|
+
|
|
188
|
+
export function createZoraHueScale(options: CreateZoraHueScaleOptions): ZoraColorScale {
|
|
189
|
+
return createScaleFromRamp({
|
|
190
|
+
hue: options.hue,
|
|
191
|
+
chromaByStep: (step) => resolveHueScaleChroma(options, step),
|
|
192
|
+
lightnessByStep: PRIMARY_LIGHTNESS_BY_STEP,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
@@ -16,10 +16,10 @@ describe('createZoraThemeConfig', () => {
|
|
|
16
16
|
expect(themeConfig.name).toBe('ZORA');
|
|
17
17
|
expect(isSixDigitHexColor(themeConfig.light.primaryColor)).toBe(true);
|
|
18
18
|
expect(themeConfig.light.harmony).toBe('analogous');
|
|
19
|
-
expect(themeConfig.light.
|
|
19
|
+
expect(themeConfig.light.colorTone).toBe('jewel');
|
|
20
20
|
expect(isSixDigitHexColor(themeConfig.dark.primaryColor)).toBe(true);
|
|
21
21
|
expect(themeConfig.dark.harmony).toBe('analogous');
|
|
22
|
-
expect(themeConfig.dark.
|
|
22
|
+
expect(themeConfig.dark.colorTone).toBe('jewel');
|
|
23
23
|
|
|
24
24
|
expect(themeConfig.light.primaryColor).not.toBe(themeConfig.dark.primaryColor);
|
|
25
25
|
|
|
@@ -33,17 +33,17 @@ describe('createZoraThemeConfig', () => {
|
|
|
33
33
|
id: 'studio',
|
|
34
34
|
primaryColor: '#0f766e',
|
|
35
35
|
harmony: 'analogous',
|
|
36
|
-
|
|
36
|
+
colorTone: 'jewel',
|
|
37
37
|
});
|
|
38
38
|
|
|
39
39
|
expect(themeConfig.id).toBe('studio');
|
|
40
40
|
expect(themeConfig.name).toBe('studio');
|
|
41
41
|
expect(isSixDigitHexColor(themeConfig.light.primaryColor)).toBe(true);
|
|
42
42
|
expect(themeConfig.light.harmony).toBe('analogous');
|
|
43
|
-
expect(themeConfig.light.
|
|
43
|
+
expect(themeConfig.light.colorTone).toBe('jewel');
|
|
44
44
|
expect(isSixDigitHexColor(themeConfig.dark.primaryColor)).toBe(true);
|
|
45
45
|
expect(themeConfig.dark.harmony).toBe('analogous');
|
|
46
|
-
expect(themeConfig.dark.
|
|
46
|
+
expect(themeConfig.dark.colorTone).toBe('jewel');
|
|
47
47
|
|
|
48
48
|
expect(themeConfig.light.primaryColor).not.toBe(themeConfig.dark.primaryColor);
|
|
49
49
|
});
|
|
@@ -11,12 +11,12 @@ export function createZoraThemeConfig(theme: ZoraTheme = zoraDefaultTheme): Them
|
|
|
11
11
|
light: {
|
|
12
12
|
primaryColor: resolveModePrimaryColor(theme.primaryColor, 'light'),
|
|
13
13
|
harmony: theme.harmony,
|
|
14
|
-
|
|
14
|
+
colorTone: theme.colorTone,
|
|
15
15
|
},
|
|
16
16
|
dark: {
|
|
17
17
|
primaryColor: resolveModePrimaryColor(theme.primaryColor, 'dark'),
|
|
18
18
|
harmony: theme.harmony,
|
|
19
|
-
|
|
19
|
+
colorTone: theme.colorTone,
|
|
20
20
|
},
|
|
21
21
|
};
|
|
22
22
|
}
|
package/src/theme/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ThemeConfig } from '@ankhorage/surface';
|
|
1
|
+
import type { ColorHarmony, ColorTone, ThemeConfig } from '@ankhorage/surface';
|
|
2
2
|
|
|
3
3
|
export type ZoraThemeId = string;
|
|
4
4
|
|
|
@@ -6,22 +6,38 @@ export type ZoraThemeMode = 'light' | 'dark';
|
|
|
6
6
|
|
|
7
7
|
export type ZoraHexColor = `#${string}`;
|
|
8
8
|
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
export const ZORA_COLOR_HARMONIES = [
|
|
10
|
+
'monochromatic',
|
|
11
|
+
'analogous',
|
|
12
|
+
'complementary',
|
|
13
|
+
'splitComplementary',
|
|
14
|
+
'triadic',
|
|
15
|
+
'tetradic',
|
|
16
|
+
] as const satisfies readonly ColorHarmony[];
|
|
16
17
|
|
|
17
|
-
export type
|
|
18
|
+
export type ZoraColorHarmony = ColorHarmony;
|
|
19
|
+
|
|
20
|
+
export const ZORA_COLOR_TONES = [
|
|
21
|
+
'neutral',
|
|
22
|
+
'pastel',
|
|
23
|
+
'earth',
|
|
24
|
+
'mineral',
|
|
25
|
+
'muted',
|
|
26
|
+
'jewel',
|
|
27
|
+
'fluorescent',
|
|
28
|
+
'obsidian',
|
|
29
|
+
'vaporwave',
|
|
30
|
+
'monochromeAccent',
|
|
31
|
+
] as const satisfies readonly ColorTone[];
|
|
32
|
+
|
|
33
|
+
export type ZoraColorTone = ColorTone;
|
|
18
34
|
|
|
19
35
|
export interface ZoraTheme {
|
|
20
36
|
id: ZoraThemeId;
|
|
21
37
|
name?: string;
|
|
22
38
|
primaryColor: ZoraHexColor;
|
|
23
39
|
harmony: ZoraColorHarmony;
|
|
24
|
-
|
|
40
|
+
colorTone: ZoraColorTone;
|
|
25
41
|
}
|
|
26
42
|
|
|
27
43
|
export interface ZoraComputedTheme {
|