okchroma 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +135 -0
- package/dist-lib/index.cjs +3924 -0
- package/dist-lib/index.mjs +3901 -0
- package/dist-lib/types/engine/alphaPapers.d.ts +14 -0
- package/dist-lib/types/engine/archetypes.d.ts +13 -0
- package/dist-lib/types/engine/collision.d.ts +43 -0
- package/dist-lib/types/engine/colorEngine.d.ts +109 -0
- package/dist-lib/types/engine/colorMath.d.ts +181 -0
- package/dist-lib/types/engine/constraints.d.ts +18 -0
- package/dist-lib/types/engine/cssRender.d.ts +32 -0
- package/dist-lib/types/engine/darkChromaCurve.d.ts +2 -0
- package/dist-lib/types/engine/figmaRender.d.ts +34 -0
- package/dist-lib/types/engine/neutralCurve.d.ts +5 -0
- package/dist-lib/types/engine/p2.d.ts +12 -0
- package/dist-lib/types/engine/perceptualL.d.ts +11 -0
- package/dist-lib/types/engine/requirements/dtcg.d.ts +44 -0
- package/dist-lib/types/engine/requirements/producers.d.ts +160 -0
- package/dist-lib/types/engine/requirements/profiles.d.ts +7 -0
- package/dist-lib/types/engine/requirements/resolve.d.ts +46 -0
- package/dist-lib/types/engine/requirements/spec.d.ts +65 -0
- package/dist-lib/types/engine/resolve.d.ts +129 -0
- package/dist-lib/types/engine/signalShift.d.ts +8 -0
- package/dist-lib/types/engine/signals.d.ts +19 -0
- package/dist-lib/types/engine/stopTable.d.ts +76 -0
- package/dist-lib/types/engine/tokenDescriptions.d.ts +18 -0
- package/dist-lib/types/engine/tokenNames.d.ts +21 -0
- package/dist-lib/types/index.d.ts +11 -0
- package/package.json +68 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { type Archetype } from '../archetypes';
|
|
2
|
+
import type { GenerateOptions } from '../colorEngine';
|
|
3
|
+
export type ResolveOpts = GenerateOptions & {
|
|
4
|
+
forcedArchetype?: Archetype;
|
|
5
|
+
};
|
|
6
|
+
export declare function buildContext(hex: string, opts?: ResolveOpts): {
|
|
7
|
+
hex: string;
|
|
8
|
+
opts: ResolveOpts | undefined;
|
|
9
|
+
brandL: number;
|
|
10
|
+
brandC: number;
|
|
11
|
+
brandH: number;
|
|
12
|
+
subtleC: number;
|
|
13
|
+
cAt: (mode: "light" | "dark", L: number, nativeC: number) => number;
|
|
14
|
+
archetype: Archetype;
|
|
15
|
+
scaleL: number;
|
|
16
|
+
darkFloorStrength: number;
|
|
17
|
+
hueIsNoise: boolean;
|
|
18
|
+
v: number;
|
|
19
|
+
vSubtle: number;
|
|
20
|
+
u: number;
|
|
21
|
+
envW: number;
|
|
22
|
+
chromaBoost: number;
|
|
23
|
+
brandSat: number;
|
|
24
|
+
lightHueAt: (L: number) => number;
|
|
25
|
+
bellAt: (L: number) => number;
|
|
26
|
+
darkH: number;
|
|
27
|
+
darkCtaH: number;
|
|
28
|
+
gOffPath: number;
|
|
29
|
+
redShift: number;
|
|
30
|
+
};
|
|
31
|
+
export type Ctx = ReturnType<typeof buildContext>;
|
|
32
|
+
export declare const lightScaleChromaAt: (ctx: Ctx, baseC: number, satFraction: number, boostOverride?: number) => (L: number) => number;
|
|
33
|
+
export declare function apcaYAt(L: number, C: number, H: number): number;
|
|
34
|
+
export declare function findMaxLForApcaLc(C: number, H: number, bgApcaY: number, targetLc: number): number;
|
|
35
|
+
export declare const APCA_SOLVE_MARGIN_LC = 0.5;
|
|
36
|
+
export declare const APCA_TOL_LC = 0.05;
|
|
37
|
+
export declare function placeLightScale(ctx: Ctx, rootL: number, chromaAt: (L: number) => number, maxLFor: ((C: number, H: number) => number) | undefined, targetChromaAt?: (L: number) => number): {
|
|
38
|
+
L: number;
|
|
39
|
+
C: number;
|
|
40
|
+
H: number;
|
|
41
|
+
};
|
|
42
|
+
export declare function separationClampLight(ctx: Ctx, placed: {
|
|
43
|
+
L: number;
|
|
44
|
+
C: number;
|
|
45
|
+
H: number;
|
|
46
|
+
}, chromaAt: (L: number) => number, ref: {
|
|
47
|
+
L: number;
|
|
48
|
+
C: number;
|
|
49
|
+
H: number;
|
|
50
|
+
}, target: number): {
|
|
51
|
+
L: number;
|
|
52
|
+
C: number;
|
|
53
|
+
H: number;
|
|
54
|
+
};
|
|
55
|
+
export declare function placeLightText(ctx: Ctx, rootL: number, cMult: number, maxLFor: (C: number, H: number) => number, deepen: number, maxC?: number): {
|
|
56
|
+
L: number;
|
|
57
|
+
C: number;
|
|
58
|
+
H: number;
|
|
59
|
+
};
|
|
60
|
+
export declare function onFillIsWhiteLight(ctx: Ctx, enforce: boolean, ratioFloor?: number): boolean;
|
|
61
|
+
export declare function buildDarkContext(ctx: Ctx, specFloorL?: number): {
|
|
62
|
+
dark9L: number;
|
|
63
|
+
darkC9: number;
|
|
64
|
+
darkHueAtL: (L: number) => number;
|
|
65
|
+
};
|
|
66
|
+
export type DarkCtx = ReturnType<typeof buildDarkContext>;
|
|
67
|
+
export declare const darkScaleChromaAt: (ctx: Ctx, dctx: DarkCtx, stopIndex: number, multiplier: number) => (L: number) => number;
|
|
68
|
+
export declare const darkInkChromaAt: (ctx: Ctx, dctx: DarkCtx, floorBase: number, multiplier: number, maxC?: number) => (L: number) => number;
|
|
69
|
+
export declare function placeDark(dctx: DarkCtx, rootL: number, chromaAt: (L: number) => number, lift?: boolean): {
|
|
70
|
+
L: number;
|
|
71
|
+
C: number;
|
|
72
|
+
H: number;
|
|
73
|
+
};
|
|
74
|
+
export declare function deltaDarkTargetL(lightColor: {
|
|
75
|
+
L: number;
|
|
76
|
+
C: number;
|
|
77
|
+
H: number;
|
|
78
|
+
}, C: number, H: number, lift?: number): number;
|
|
79
|
+
export declare function cuspDarknessW(H: number): number;
|
|
80
|
+
export declare function deltaDarkPlace(lightStops: Array<{
|
|
81
|
+
stop: number;
|
|
82
|
+
L: number;
|
|
83
|
+
C: number;
|
|
84
|
+
H: number;
|
|
85
|
+
}>, lightTwin: {
|
|
86
|
+
L: number;
|
|
87
|
+
C: number;
|
|
88
|
+
H: number;
|
|
89
|
+
}, lift: number, _tStop: number, grayLightL?: number): {
|
|
90
|
+
L: number;
|
|
91
|
+
C: number;
|
|
92
|
+
};
|
|
93
|
+
export declare function smoothedBandLift(stop: number): number;
|
|
94
|
+
export declare function deltaLiftChroma(lightStops: Array<{
|
|
95
|
+
stop: number;
|
|
96
|
+
L: number;
|
|
97
|
+
C: number;
|
|
98
|
+
H: number;
|
|
99
|
+
}>, lightTwin: {
|
|
100
|
+
L: number;
|
|
101
|
+
C: number;
|
|
102
|
+
H: number;
|
|
103
|
+
}, lift: number): number;
|
|
104
|
+
export declare function placeDarkDelta(dctx: DarkCtx, rootL: number, chromaAt: (L: number) => number, lightStop: {
|
|
105
|
+
L: number;
|
|
106
|
+
C: number;
|
|
107
|
+
H: number;
|
|
108
|
+
}): {
|
|
109
|
+
L: number;
|
|
110
|
+
C: number;
|
|
111
|
+
H: number;
|
|
112
|
+
};
|
|
113
|
+
export declare function flatDarkCtaL(dctx: DarkCtx, chromaAt: (L: number) => number, H: number, gapApp: number): number;
|
|
114
|
+
export declare function ctaLightL(ctx: Ctx, onFillTextIsWhite: boolean, enforce: boolean): number;
|
|
115
|
+
export declare function ctaDarkEnforcedL(ctx: Ctx, base: {
|
|
116
|
+
L: number;
|
|
117
|
+
C: number;
|
|
118
|
+
H: number;
|
|
119
|
+
}, onFillIsWhiteDark: boolean, enforce: boolean): number | null;
|
|
120
|
+
export declare const whiteTextLcAt: (L: number, C: number, H: number) => number;
|
|
121
|
+
export declare function findLForWhiteTextLc(startL: number, C: number, H: number, targetLc: number): number;
|
|
122
|
+
export declare const APCA_ENFORCE_MARGIN_LC = 2;
|
|
123
|
+
export declare function ctaLightLApca(ctx: Ctx, onFillTextIsWhite: boolean, enforce: boolean, thresholdLc: number): number;
|
|
124
|
+
export declare function ctaDarkEnforcedLApca(ctx: Ctx, base: {
|
|
125
|
+
L: number;
|
|
126
|
+
C: number;
|
|
127
|
+
H: number;
|
|
128
|
+
}, onFillIsWhiteDark: boolean, enforce: boolean, thresholdLc: number): number | null;
|
|
129
|
+
export declare const blackTextLcAt: (L: number, C: number, H: number) => number;
|
|
130
|
+
export declare function findLForBlackTextLc(startL: number, C: number, H: number, targetLc: number, capHiL: number): number;
|
|
131
|
+
export declare function ctaDualGateL(ctx: Ctx, onFillTextIsWhite: boolean, enforce: boolean, coLc: number, capLoL: number, capHiL: number): number;
|
|
132
|
+
export declare function ctaDarkDualGateL(base: {
|
|
133
|
+
L: number;
|
|
134
|
+
C: number;
|
|
135
|
+
}, darkH: number, onFillTextIsWhite: boolean, enforce: boolean, coLc: number, capLoL: number, capHiL: number): number;
|
|
136
|
+
export declare function onFillIsWhiteDarkAt(L: number, C: number, H: number, enforce: boolean, ratioFloor?: number): boolean;
|
|
137
|
+
export interface BrandExitLanding {
|
|
138
|
+
L: number;
|
|
139
|
+
H: number;
|
|
140
|
+
cMul: number;
|
|
141
|
+
up: boolean;
|
|
142
|
+
}
|
|
143
|
+
export declare function solveBrandExit(seed: {
|
|
144
|
+
L: number;
|
|
145
|
+
C: number;
|
|
146
|
+
H: number;
|
|
147
|
+
}, cFor: (L: number) => number, brandH: number, red: {
|
|
148
|
+
L: number;
|
|
149
|
+
C: number;
|
|
150
|
+
H: number;
|
|
151
|
+
}, enforceLc?: number, coLc?: number): BrandExitLanding | null;
|
|
152
|
+
export declare function solveDarkCtaExit(cur: {
|
|
153
|
+
L: number;
|
|
154
|
+
C: number;
|
|
155
|
+
H: number;
|
|
156
|
+
}, cFor: (L: number) => number, darkH: number, redDark: {
|
|
157
|
+
L: number;
|
|
158
|
+
C: number;
|
|
159
|
+
H: number;
|
|
160
|
+
}, enforceLc?: number, coLc?: number): number | null;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ModeSpec } from './spec';
|
|
2
|
+
export type ContrastProfile = 'wcag' | 'apca';
|
|
3
|
+
export type LcMap = Record<number, number>;
|
|
4
|
+
export declare const DEFAULT_APCA_LC_MAP: LcMap;
|
|
5
|
+
export declare const CTA_ONFILL_ENFORCE_LC = 60;
|
|
6
|
+
export declare const CRITICAL_CLEARANCE_LC = 50;
|
|
7
|
+
export declare function withProfile(spec: ModeSpec, profile: ContrastProfile, lcMap?: LcMap): ModeSpec;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type ModeSpec, type RoleReq } from './spec';
|
|
2
|
+
import { type ResolveOpts } from './producers';
|
|
3
|
+
export type ResolvedStop = {
|
|
4
|
+
stop: number;
|
|
5
|
+
group: string;
|
|
6
|
+
L: number;
|
|
7
|
+
C: number;
|
|
8
|
+
H: number;
|
|
9
|
+
hex: string;
|
|
10
|
+
Y: number;
|
|
11
|
+
appL: number;
|
|
12
|
+
clamped: boolean;
|
|
13
|
+
unresolvable?: string;
|
|
14
|
+
};
|
|
15
|
+
export type ResolvedRole = {
|
|
16
|
+
role: RoleReq['role'];
|
|
17
|
+
L: number;
|
|
18
|
+
C: number;
|
|
19
|
+
H: number;
|
|
20
|
+
hex: string;
|
|
21
|
+
Y: number;
|
|
22
|
+
appL: number;
|
|
23
|
+
enforced?: boolean;
|
|
24
|
+
repelled?: boolean;
|
|
25
|
+
};
|
|
26
|
+
export type Seed = {
|
|
27
|
+
hex: string;
|
|
28
|
+
L: number;
|
|
29
|
+
C: number;
|
|
30
|
+
H: number;
|
|
31
|
+
};
|
|
32
|
+
export type ResolvedRamp = {
|
|
33
|
+
mode: 'light' | 'dark';
|
|
34
|
+
seed: Seed;
|
|
35
|
+
stops: ResolvedStop[];
|
|
36
|
+
roles: {
|
|
37
|
+
cta: ResolvedRole;
|
|
38
|
+
ctaHover: ResolvedRole;
|
|
39
|
+
ctaPressed: ResolvedRole;
|
|
40
|
+
};
|
|
41
|
+
ons: {
|
|
42
|
+
onFillIsWhite: boolean;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
export type { ResolveOpts };
|
|
46
|
+
export declare function resolveRamp(hex: string, mode: 'light' | 'dark', spec?: ModeSpec, opts?: ResolveOpts): ResolvedRamp;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export type Group = 'paper' | 'wash' | 'highlight' | 'ink';
|
|
2
|
+
export type Producer = {
|
|
3
|
+
hue: 'warm-drift' | 'warm-torsion' | 'constant';
|
|
4
|
+
L: 'perceptual' | 'perceptual-lift' | 'fixed';
|
|
5
|
+
chroma: 'ladder' | 'brand';
|
|
6
|
+
};
|
|
7
|
+
export type Require = {
|
|
8
|
+
metric: 'wcag';
|
|
9
|
+
against: 'paper-99' | 'paper-97' | 'paper-95' | 'wash-80';
|
|
10
|
+
target: number;
|
|
11
|
+
level: 'AA' | 'AAA';
|
|
12
|
+
} | {
|
|
13
|
+
metric: 'apca';
|
|
14
|
+
against: 'paper-99' | 'paper-97' | 'paper-95';
|
|
15
|
+
targetLc: number;
|
|
16
|
+
} | {
|
|
17
|
+
metric: 'min-separation';
|
|
18
|
+
against: 'paper-99' | 'prev';
|
|
19
|
+
target: number;
|
|
20
|
+
};
|
|
21
|
+
export type StopReq = {
|
|
22
|
+
stop: number;
|
|
23
|
+
rootL: number;
|
|
24
|
+
group: Group;
|
|
25
|
+
produce: Producer;
|
|
26
|
+
satFraction?: number;
|
|
27
|
+
baseC?: number;
|
|
28
|
+
chromaMult?: number;
|
|
29
|
+
inkMaxC?: number;
|
|
30
|
+
chromaFloor?: number;
|
|
31
|
+
require?: Require;
|
|
32
|
+
};
|
|
33
|
+
export type RoleName = 'cta' | 'cta-hover' | 'cta-pressed';
|
|
34
|
+
export type RoleReq = {
|
|
35
|
+
role: RoleName;
|
|
36
|
+
produce: {
|
|
37
|
+
hue: 'constant';
|
|
38
|
+
L: 'anchor' | 'hover' | 'pressed';
|
|
39
|
+
chroma: 'brand';
|
|
40
|
+
};
|
|
41
|
+
floorL: number;
|
|
42
|
+
chromaMult: number;
|
|
43
|
+
};
|
|
44
|
+
export type OnReq = {
|
|
45
|
+
metric: 'apca-pole';
|
|
46
|
+
enforce: boolean;
|
|
47
|
+
enforceLc?: number;
|
|
48
|
+
ratioFloor?: number;
|
|
49
|
+
coEnforceLc?: number;
|
|
50
|
+
};
|
|
51
|
+
export type ModeSpec = {
|
|
52
|
+
stops: StopReq[];
|
|
53
|
+
roles: RoleReq[];
|
|
54
|
+
ons: {
|
|
55
|
+
onFill: OnReq;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
export declare const PAPER0_DARK_ROOT_L = 0.16;
|
|
59
|
+
export declare const INK0_SEAM_OVERSHOOT: number;
|
|
60
|
+
export declare const LIGHT: ModeSpec;
|
|
61
|
+
export declare const DARK: ModeSpec;
|
|
62
|
+
export declare const MODE_SPECS: {
|
|
63
|
+
light: ModeSpec;
|
|
64
|
+
dark: ModeSpec;
|
|
65
|
+
};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { type GeneratedScale, type ContrastProfile, type ColorStop } from './colorEngine';
|
|
2
|
+
import type { Archetype } from './archetypes';
|
|
3
|
+
import { type SignalDef } from './signals';
|
|
4
|
+
type SignalScales = Map<SignalDef['name'], {
|
|
5
|
+
def: SignalDef;
|
|
6
|
+
scale: GeneratedScale;
|
|
7
|
+
}>;
|
|
8
|
+
export declare const SIGNAL_SCALES: SignalScales;
|
|
9
|
+
export declare function signalScalesFor(contrastProfile?: ContrastProfile): SignalScales;
|
|
10
|
+
export interface SignalOverride {
|
|
11
|
+
name: SignalDef['name'];
|
|
12
|
+
scale: GeneratedScale;
|
|
13
|
+
note: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ResolvedBrand {
|
|
16
|
+
scale: GeneratedScale;
|
|
17
|
+
shearDeg: number;
|
|
18
|
+
redRepel: {
|
|
19
|
+
light: boolean;
|
|
20
|
+
dark: boolean;
|
|
21
|
+
} | null;
|
|
22
|
+
warningVariant: 'lemon' | 'macaroni' | null;
|
|
23
|
+
pending: SignalDef['name'][];
|
|
24
|
+
signalOverrides: SignalOverride[];
|
|
25
|
+
}
|
|
26
|
+
export declare function resolveBrand(hex: string, name: string, opts?: {
|
|
27
|
+
exact?: boolean;
|
|
28
|
+
archetypeOverride?: Archetype;
|
|
29
|
+
style?: 'default' | 'deeper' | 'full-chroma';
|
|
30
|
+
contrastProfile?: ContrastProfile;
|
|
31
|
+
skipCollisionRules?: boolean;
|
|
32
|
+
apcaClearance?: boolean;
|
|
33
|
+
darkCtaFlatApp?: number;
|
|
34
|
+
inkGround?: {
|
|
35
|
+
light: {
|
|
36
|
+
L: number;
|
|
37
|
+
C: number;
|
|
38
|
+
H: number;
|
|
39
|
+
};
|
|
40
|
+
dark: {
|
|
41
|
+
L: number;
|
|
42
|
+
C: number;
|
|
43
|
+
H: number;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
}): ResolvedBrand;
|
|
47
|
+
export type SecondaryLevel = 'standard' | 'subtle';
|
|
48
|
+
export type SecondaryStyle = 'default' | 'outline' | 'exact';
|
|
49
|
+
export type LegacySecondaryStyle = SecondaryStyle | 'tint' | 'pastel' | 'muted' | 'vibrant';
|
|
50
|
+
export declare const normalizeSecondaryStyle: (s: LegacySecondaryStyle) => SecondaryStyle;
|
|
51
|
+
export declare const DEFAULT_SECONDARY: {
|
|
52
|
+
readonly kL: 0.65;
|
|
53
|
+
readonly kC: 0.5;
|
|
54
|
+
readonly kR: 0.4;
|
|
55
|
+
readonly lRoom: 0.97;
|
|
56
|
+
readonly minGapApp: 10;
|
|
57
|
+
readonly darkFlatGapApp: 40;
|
|
58
|
+
};
|
|
59
|
+
export declare function defaultSecondarySeed(hex: string): string;
|
|
60
|
+
export declare const SUBTLE_TINT_MULT = 8;
|
|
61
|
+
export declare const SUBTLE_PASTEL_K = 0.35;
|
|
62
|
+
export declare const OUTLINE_HOVER_ALPHA = 0.09;
|
|
63
|
+
export declare const OUTLINE_PRESSED_ALPHA = 0.18;
|
|
64
|
+
export declare const SOFT_ON_CTA_ALPHA: {
|
|
65
|
+
readonly light: 0.75;
|
|
66
|
+
readonly dark: 0.8;
|
|
67
|
+
};
|
|
68
|
+
export declare function softOnCtaPasses(s: GeneratedScale, mode: 'light' | 'dark'): boolean;
|
|
69
|
+
export declare const DEFAULT_LINK_HEX = "#0B57D0";
|
|
70
|
+
export declare function resolveLinkTrio(linkHex: string, contrastProfile?: ContrastProfile): {
|
|
71
|
+
link: ColorStop;
|
|
72
|
+
linkHover: ColorStop;
|
|
73
|
+
linkPressed: ColorStop;
|
|
74
|
+
linkDark: ColorStop;
|
|
75
|
+
linkHoverDark: ColorStop;
|
|
76
|
+
linkPressedDark: ColorStop;
|
|
77
|
+
};
|
|
78
|
+
export declare function resolveLinkInverseTrio(seedHex: string, contrastProfile?: ContrastProfile): {
|
|
79
|
+
link: ColorStop;
|
|
80
|
+
linkHover: ColorStop;
|
|
81
|
+
linkPressed: ColorStop;
|
|
82
|
+
linkDark: ColorStop;
|
|
83
|
+
linkHoverDark: ColorStop;
|
|
84
|
+
linkPressedDark: ColorStop;
|
|
85
|
+
};
|
|
86
|
+
export declare function escapeCtaFamily(nScale: GeneratedScale, mode: 'light' | 'dark', contrastProfile?: ContrastProfile): {
|
|
87
|
+
cta: ColorStop;
|
|
88
|
+
ctaHover: ColorStop;
|
|
89
|
+
ctaPressed: ColorStop;
|
|
90
|
+
onFillIsWhite: boolean;
|
|
91
|
+
};
|
|
92
|
+
export interface ResolvedSecondary {
|
|
93
|
+
scale: GeneratedScale;
|
|
94
|
+
style: SecondaryStyle;
|
|
95
|
+
level: SecondaryLevel;
|
|
96
|
+
demoted: boolean;
|
|
97
|
+
derived: boolean;
|
|
98
|
+
notes: string[];
|
|
99
|
+
distinctness: {
|
|
100
|
+
light: number;
|
|
101
|
+
dark: number;
|
|
102
|
+
close: boolean;
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
export interface ResolvedTheme {
|
|
106
|
+
primary: ResolvedBrand;
|
|
107
|
+
themed: ResolvedBrand;
|
|
108
|
+
secondary: ResolvedSecondary | null;
|
|
109
|
+
signalOverrides: SignalOverride[];
|
|
110
|
+
notes: string[];
|
|
111
|
+
}
|
|
112
|
+
export declare const SECONDARY_DISTINCT_DELTA_E = 0.12;
|
|
113
|
+
export declare function resolveTheme(input: {
|
|
114
|
+
primaryHex: string;
|
|
115
|
+
name?: string;
|
|
116
|
+
primaryMode?: 'recommended' | 'exact';
|
|
117
|
+
primaryArchetype?: Archetype;
|
|
118
|
+
secondaryHex?: string | null;
|
|
119
|
+
secondaryStyle?: LegacySecondaryStyle;
|
|
120
|
+
secondaryLevel?: SecondaryLevel;
|
|
121
|
+
secondaryArchetype?: Archetype;
|
|
122
|
+
deriveSecondary?: boolean;
|
|
123
|
+
exact?: boolean;
|
|
124
|
+
style?: 'default' | 'deeper' | 'full-chroma';
|
|
125
|
+
archetypeOverride?: Archetype;
|
|
126
|
+
contrastProfile?: ContrastProfile;
|
|
127
|
+
apcaClearance?: boolean;
|
|
128
|
+
}): ResolvedTheme;
|
|
129
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type GeneratedScale, type ContrastProfile } from './colorEngine';
|
|
2
|
+
import type { SignalDef } from './signals';
|
|
3
|
+
export interface ShiftResult {
|
|
4
|
+
scale: GeneratedScale;
|
|
5
|
+
note: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function signalSwapVariants(def: SignalDef, contrastProfile?: ContrastProfile): ShiftResult[];
|
|
8
|
+
export declare function pickSignalShift(brand: GeneratedScale, canonicalSignalScale: GeneratedScale, def: SignalDef, contrastProfile?: ContrastProfile): ShiftResult | null;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { FAMILY } from './tokenDescriptions';
|
|
2
|
+
type SignalFamily = (typeof FAMILY)['critical' | 'warning' | 'positive' | 'info'];
|
|
3
|
+
export interface SignalDef {
|
|
4
|
+
name: 'red' | 'yellow' | 'green' | 'blue';
|
|
5
|
+
emitName: SignalFamily;
|
|
6
|
+
hex: string;
|
|
7
|
+
L: number;
|
|
8
|
+
C: number;
|
|
9
|
+
H: number;
|
|
10
|
+
hueShift: {
|
|
11
|
+
cool: number;
|
|
12
|
+
warm: number;
|
|
13
|
+
};
|
|
14
|
+
yieldChromaScale: number;
|
|
15
|
+
darkFillMinL?: number;
|
|
16
|
+
}
|
|
17
|
+
export declare const SIGNALS: SignalDef[];
|
|
18
|
+
export declare const SIGNAL_EMIT_NAME: Record<SignalDef['name'], SignalDef['emitName']>;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export interface StopSpec {
|
|
2
|
+
rootL: number;
|
|
3
|
+
chromaMultiplier: number;
|
|
4
|
+
}
|
|
5
|
+
export declare const ROOT_L_LIGHT: Record<number, number>;
|
|
6
|
+
export declare const ROOT_L_DARK: Record<number, number>;
|
|
7
|
+
export declare const chromaFloorBase: (idx: number) => number;
|
|
8
|
+
export interface ScaleChroma {
|
|
9
|
+
base?: number;
|
|
10
|
+
sat?: number;
|
|
11
|
+
inkMult?: number;
|
|
12
|
+
inkMaxC?: number;
|
|
13
|
+
chromaFloor?: number;
|
|
14
|
+
}
|
|
15
|
+
export declare const SCALE_C_LIGHT: Record<number, ScaleChroma>;
|
|
16
|
+
export declare const SCALE_C_DARK: Record<number, ScaleChroma>;
|
|
17
|
+
export declare const DARK_CTA_C: {
|
|
18
|
+
brand: {
|
|
19
|
+
policy: "trimmed";
|
|
20
|
+
globalTrim: number;
|
|
21
|
+
lobes: {
|
|
22
|
+
center: number;
|
|
23
|
+
width: number;
|
|
24
|
+
depth: number;
|
|
25
|
+
}[];
|
|
26
|
+
};
|
|
27
|
+
signal: {
|
|
28
|
+
policy: "identity";
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
export type DarkCtaKind = keyof typeof DARK_CTA_C;
|
|
32
|
+
export declare const STOP_8_NONTEXT_CONTRAST = 3;
|
|
33
|
+
export declare const DARK_BAND_TOP_LIFT = 1.19;
|
|
34
|
+
export declare const YELLOW_BAND: {
|
|
35
|
+
centerH: number;
|
|
36
|
+
sigmaDeg: number;
|
|
37
|
+
};
|
|
38
|
+
export declare const INK_9_CONTRAST = 4.5;
|
|
39
|
+
export declare const INK_10_CONTRAST = 4.5;
|
|
40
|
+
export declare const INK_11_CONTRAST_FLOOR = 7;
|
|
41
|
+
export declare const INK_30_GROUND: {
|
|
42
|
+
readonly wcag: {
|
|
43
|
+
readonly light: {
|
|
44
|
+
readonly L: 0.3334966864733433;
|
|
45
|
+
readonly C: 0.07399966383476321;
|
|
46
|
+
readonly H: 104.26776675496032;
|
|
47
|
+
};
|
|
48
|
+
readonly dark: {
|
|
49
|
+
readonly L: 0.907688606079988;
|
|
50
|
+
readonly C: 0.045;
|
|
51
|
+
readonly H: 293.66431934911327;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
readonly apca: {
|
|
55
|
+
readonly light: {
|
|
56
|
+
readonly L: 0.3334966864733433;
|
|
57
|
+
readonly C: 0.07399966383476321;
|
|
58
|
+
readonly H: 104.26776675496032;
|
|
59
|
+
};
|
|
60
|
+
readonly dark: {
|
|
61
|
+
readonly L: 0.9183200227624329;
|
|
62
|
+
readonly C: 0.045;
|
|
63
|
+
readonly H: 153.30922413895024;
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
export declare const DARK_CTA_MIN_L = 0.63;
|
|
68
|
+
export declare const DARK_BRAND_FILL_MIN_L = 0.7;
|
|
69
|
+
export declare const DARK_SIGNAL_WARM_DRIFT: number;
|
|
70
|
+
export declare const NEUTRAL_CTA_DARK_POP_CLEARANCE = 1.2;
|
|
71
|
+
export declare const GOLD_SPINE: Array<[number, number]>;
|
|
72
|
+
export declare const WARM_TORSION: {
|
|
73
|
+
weight: Array<[number, number]>;
|
|
74
|
+
travel: number;
|
|
75
|
+
capDeg: number;
|
|
76
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare const FAMILY: {
|
|
2
|
+
readonly neutral: "neutral";
|
|
3
|
+
readonly brandPrimary: "brand";
|
|
4
|
+
readonly brandSecondary: "brand-alt";
|
|
5
|
+
readonly critical: "critical";
|
|
6
|
+
readonly warning: "warning";
|
|
7
|
+
readonly positive: "positive";
|
|
8
|
+
readonly info: "info";
|
|
9
|
+
};
|
|
10
|
+
export type Family = (typeof FAMILY)[keyof typeof FAMILY];
|
|
11
|
+
export declare const FAMILIES: readonly Family[];
|
|
12
|
+
export declare const CSS_FAMILY: {
|
|
13
|
+
readonly neutral: "neutral";
|
|
14
|
+
readonly brandPrimary: "brand";
|
|
15
|
+
readonly brandSecondary: "brand-alt";
|
|
16
|
+
};
|
|
17
|
+
export declare function canonicalize(path: string): string;
|
|
18
|
+
export declare function describeToken(path: string): string;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const SCALE_STOP_COUNT: number;
|
|
2
|
+
export declare function stopTokenName(stop: number): string;
|
|
3
|
+
export declare const PAPER_100 = "paper-100";
|
|
4
|
+
export declare const INK_0 = "ink-0";
|
|
5
|
+
export declare const STAMP_FILL = "stamp-fill";
|
|
6
|
+
export declare const STAMP_FILL_HOVER = "stamp-fill-hover";
|
|
7
|
+
export declare const STAMP_FILL_PRESSED = "stamp-fill-pressed";
|
|
8
|
+
export declare const STAMP_EDGE = "stamp-edge";
|
|
9
|
+
export declare const STAMP_ON = "stamp-on";
|
|
10
|
+
export declare const STAMP_STATE_LEAVES: Record<string, string>;
|
|
11
|
+
export declare const STAMP_LEAF: {
|
|
12
|
+
readonly FILL: string;
|
|
13
|
+
readonly FILL_HOVER: string;
|
|
14
|
+
readonly FILL_PRESSED: string;
|
|
15
|
+
readonly EDGE: string;
|
|
16
|
+
readonly ON: string;
|
|
17
|
+
};
|
|
18
|
+
export declare const CONTRACT_INVARIANT_ROWS: ReadonlySet<string>;
|
|
19
|
+
export declare const EXT_NON_OVERRIDABLE: (p: string) => boolean;
|
|
20
|
+
export declare const EXT_OVERRIDABLE_SYSTEM: (p: string) => boolean;
|
|
21
|
+
export declare function tokenOrder(name: string): number;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { generateScale, generateNeutralScale, generateSubtleSecondary, type GeneratedScale, type ColorStop, type GenerateOptions, type NeutralLevel, type ContrastProfile, } from './engine/colorEngine';
|
|
2
|
+
export { resolveBrand, resolveTheme, resolveLinkTrio, resolveLinkInverseTrio, DEFAULT_LINK_HEX, SIGNAL_SCALES, signalScalesFor, SECONDARY_DISTINCT_DELTA_E, SUBTLE_TINT_MULT, SUBTLE_PASTEL_K, OUTLINE_HOVER_ALPHA, type ResolvedBrand, type ResolvedTheme, type ResolvedSecondary, type SecondaryLevel, type SecondaryStyle, type SignalOverride, } from './engine/resolve';
|
|
3
|
+
export { brandCss, neutralCss, signalsCss, stopsToVars, toHex, stopHex, OFFSET_ALPHAS } from './engine/cssRender';
|
|
4
|
+
export { themeToFigma, type FigmaGroup, type FigmaColorToken, type ThemeInput, } from './engine/figmaRender';
|
|
5
|
+
export { emitDtcgRamp, resolveDtcgRamp, parseToken, EXT_KEY, RESOLVER_ID, type DtcgRampGroup, type DtcgRequirementToken, type DtcgSeedToken, type DtcgColorValue, } from './engine/requirements/dtcg';
|
|
6
|
+
export { MODE_SPECS, type ModeSpec } from './engine/requirements/spec';
|
|
7
|
+
export { stopTokenName, tokenOrder, SCALE_STOP_COUNT, PAPER_100, INK_0, STAMP_FILL, STAMP_FILL_HOVER, STAMP_FILL_PRESSED, STAMP_EDGE, STAMP_ON, STAMP_STATE_LEAVES, } from './engine/tokenNames';
|
|
8
|
+
export { SIGNAL_EMIT_NAME } from './engine/signals';
|
|
9
|
+
export { classifyArchetype, type Archetype } from './engine/archetypes';
|
|
10
|
+
export { SIGNALS, type SignalDef } from './engine/signals';
|
|
11
|
+
export { checkCollision, checkHueCollision, checkAllCollisions, type HueCollisionCheck } from './engine/collision';
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "okchroma",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"description": "Color token engine: one brand hex in, a full WCAG-enforced light+dark token system out (CSS variables, DTCG JSON, Figma variables)",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/egerrity/okchroma.git"
|
|
9
|
+
},
|
|
10
|
+
"main": "./dist-lib/index.cjs",
|
|
11
|
+
"module": "./dist-lib/index.mjs",
|
|
12
|
+
"types": "./dist-lib/types/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist-lib/types/index.d.ts",
|
|
16
|
+
"import": "./dist-lib/index.mjs",
|
|
17
|
+
"require": "./dist-lib/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist-lib"
|
|
22
|
+
],
|
|
23
|
+
"sideEffects": false,
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build:lib": "node esbuild.config.js --lib && tsc -p tsconfig.lib.json",
|
|
26
|
+
"prepack": "npm run build:lib",
|
|
27
|
+
"generate": "node dist/build-script.js",
|
|
28
|
+
"demo:build": "node esbuild.config.js",
|
|
29
|
+
"build": "node esbuild.config.js",
|
|
30
|
+
"dev": "node esbuild.config.js --watch",
|
|
31
|
+
"audit": "esbuild scripts/dark-audit.ts --bundle --platform=node --outfile=dist/dark-audit.js && node dist/dark-audit.js",
|
|
32
|
+
"audit:alpha": "esbuild scripts/alpha-audit.ts --bundle --platform=node --outfile=dist/alpha-audit.js && node dist/alpha-audit.js",
|
|
33
|
+
"audit:alpha:bless": "esbuild scripts/alpha-audit.ts --bundle --platform=node --outfile=dist/alpha-audit.js && node dist/alpha-audit.js --bless",
|
|
34
|
+
"audit:bless": "esbuild scripts/dark-audit.ts --bundle --platform=node --outfile=dist/dark-audit.js && node dist/dark-audit.js --bless",
|
|
35
|
+
"highlight-audit": "esbuild scripts/highlight-audit.ts --bundle --platform=node --outfile=dist/highlight-audit.js && node dist/highlight-audit.js",
|
|
36
|
+
"highlight-audit:bless": "esbuild scripts/highlight-audit.ts --bundle --platform=node --outfile=dist/highlight-audit.js && node dist/highlight-audit.js --bless",
|
|
37
|
+
"audit:divergence": "esbuild scripts/divergence-audit.ts --bundle --platform=node --outfile=dist/divergence-audit.js && node dist/divergence-audit.js",
|
|
38
|
+
"audit:divergence:bless": "esbuild scripts/divergence-audit.ts --bundle --platform=node --outfile=dist/divergence-audit.js && node dist/divergence-audit.js --bless",
|
|
39
|
+
"smooth": "esbuild scripts/smoothness-audit.ts --bundle --platform=node --outfile=dist/smoothness-audit.js && node dist/smoothness-audit.js",
|
|
40
|
+
"smooth:baseline": "esbuild scripts/smoothness-audit.ts --bundle --platform=node --outfile=dist/smoothness-audit.js && node dist/smoothness-audit.js --baseline",
|
|
41
|
+
"figma:verify": "esbuild scripts/figma-verify.ts --bundle --platform=node --outfile=dist/figma-verify.js && node dist/figma-verify.js",
|
|
42
|
+
"req:audit": "esbuild scripts/reqtoken-audit.ts --bundle --platform=node --outfile=dist/reqtoken-audit.js && node dist/reqtoken-audit.js",
|
|
43
|
+
"audit:secondary": "esbuild scripts/secondary-audit.ts --bundle --platform=node --outfile=dist/secondary-audit.js && node dist/secondary-audit.js",
|
|
44
|
+
"audit:guarantee": "esbuild scripts/guarantee-audit.ts --bundle --platform=node --outfile=dist/guarantee-audit.js && node dist/guarantee-audit.js",
|
|
45
|
+
"plugin:build": "node esbuild.config.js --plugin",
|
|
46
|
+
"plugin-unify:build": "node esbuild.config.js --plugin-unify",
|
|
47
|
+
"plugin-ext:build": "node esbuild.config.js --plugin-ext",
|
|
48
|
+
"audit:register": "esbuild scripts/register-audit.ts --bundle --platform=node --outfile=dist/register-audit.js && node dist/register-audit.js",
|
|
49
|
+
"audit:ext": "esbuild scripts/ext-override-audit.ts --bundle --platform=node --outfile=dist/ext-override-audit.js && node dist/ext-override-audit.js",
|
|
50
|
+
"audit:ext:bless": "esbuild scripts/ext-override-audit.ts --bundle --platform=node --outfile=dist/ext-override-audit.js && node dist/ext-override-audit.js --bless",
|
|
51
|
+
"audit:cta-apca": "esbuild scripts/cta-apca-audit.ts --bundle --platform=node --outfile=dist/cta-apca-audit.js && node dist/cta-apca-audit.js",
|
|
52
|
+
"audit:desc": "esbuild scripts/desc-audit.ts --bundle --platform=node --outfile=dist/desc-audit.js && node dist/desc-audit.js",
|
|
53
|
+
"name-lint": "esbuild scripts/name-lint.ts --bundle --platform=node --outfile=dist/name-lint.js && node dist/name-lint.js",
|
|
54
|
+
"typecheck": "tsc --noEmit",
|
|
55
|
+
"typecheck:ext": "tsc --noEmit -p plugin-ext"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@types/node": "^25.9.2",
|
|
59
|
+
"@types/react": "^18.3.0",
|
|
60
|
+
"@types/react-dom": "^18.3.0",
|
|
61
|
+
"esbuild": "^0.28.1",
|
|
62
|
+
"helmlab": "^0.14.0",
|
|
63
|
+
"lucide-react": "^1.17.0",
|
|
64
|
+
"react": "^18.3.0",
|
|
65
|
+
"react-dom": "^18.3.0",
|
|
66
|
+
"typescript": "^5.4.0"
|
|
67
|
+
}
|
|
68
|
+
}
|