astralkit 0.6.0 → 0.7.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/CHANGELOG.md +15 -0
- package/LICENSE +73 -34
- package/README.md +31 -1
- package/astralkit-theme-v4.css +135 -114
- package/astralkit-theme.css +135 -114
- package/astralkit-utilities.css +312 -1
- package/lib/presets/appearance-presets.d.ts +12 -0
- package/lib/presets/appearance-presets.js +102 -0
- package/lib/presets/chart-palettes.d.ts +29 -0
- package/lib/presets/chart-palettes.js +99 -0
- package/lib/presets/dials.d.ts +31 -0
- package/lib/presets/dials.js +330 -0
- package/lib/presets/font-pairings.d.ts +29 -0
- package/lib/presets/font-pairings.js +123 -0
- package/lib/presets/fonts.d.ts +16 -0
- package/lib/presets/fonts.js +76 -0
- package/lib/presets/index.d.ts +7 -0
- package/lib/presets/index.js +24 -0
- package/lib/presets/materials.d.ts +15 -0
- package/lib/presets/materials.js +245 -0
- package/lib/presets/theme-palettes.d.ts +90 -0
- package/lib/presets/theme-palettes.js +720 -0
- package/package.json +3 -2
- package/primitives/animations.css +43 -1
- package/tailwind.cjs +15 -9
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* astralkit/presets — material appearances.
|
|
3
|
+
*
|
|
4
|
+
* An APPEARANCE is a design language: the physical properties of the UI —
|
|
5
|
+
* surface fill/blur, border weight, shadow character, press behavior, type
|
|
6
|
+
* weight — expressed as a pack of --ak-material slots. Components consume
|
|
7
|
+
* the slots via the SDK recipes (.ak-material-control / .ak-material-surface
|
|
8
|
+
* / .ak-press); switching packs re-materializes a RUNNING app.
|
|
9
|
+
*
|
|
10
|
+
* Composability is the point: Appearance × Palette × Radius × Type Scale,
|
|
11
|
+
* all runtime. shadcn's styles are frozen skins baked at scaffold time —
|
|
12
|
+
* this dial is the thing that architecture cannot do.
|
|
13
|
+
*
|
|
14
|
+
* Each pack: light `variables`, authored `darkVariables`, and a suggested
|
|
15
|
+
* `radius` (applied only while the Radius dial sits on Default — an explicit
|
|
16
|
+
* radius pick always wins).
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export const DEFAULT_MATERIAL_ID = 'soft'
|
|
20
|
+
|
|
21
|
+
const INK = '#0a0a0a'
|
|
22
|
+
const PAPER = '#f4f4f5'
|
|
23
|
+
|
|
24
|
+
export const MATERIAL_APPEARANCES = [
|
|
25
|
+
{
|
|
26
|
+
id: 'soft',
|
|
27
|
+
name: 'Soft',
|
|
28
|
+
description: 'The house default — quiet borders, calm surfaces.',
|
|
29
|
+
radius: null,
|
|
30
|
+
variables: {},
|
|
31
|
+
darkVariables: {},
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: 'flat',
|
|
35
|
+
name: 'Flat',
|
|
36
|
+
description: 'Zero elevation, crisp hairlines, sharp corners.',
|
|
37
|
+
radius: '0.375rem',
|
|
38
|
+
variables: {
|
|
39
|
+
'--ak-control-shadow': 'none',
|
|
40
|
+
'--ak-surface-shadow': 'none',
|
|
41
|
+
'--ak-surface-border-color': 'var(--color-ak-border-strong)',
|
|
42
|
+
'--ak-press-transform': 'scale(0.99)',
|
|
43
|
+
// Zero elevation extends to the small parts: crisp bordered thumb,
|
|
44
|
+
// shadowless knob, flat tracks, no hover theatrics.
|
|
45
|
+
'--ak-knob-shadow': 'none',
|
|
46
|
+
'--ak-thumb-shadow': 'none',
|
|
47
|
+
'--ak-thumb-border-w': '1px',
|
|
48
|
+
'--ak-thumb-border-color': 'var(--color-ak-border-strong)',
|
|
49
|
+
'--ak-thumb-hover-transform': 'none',
|
|
50
|
+
'--ak-track-shadow': '0 0 0 0 transparent',
|
|
51
|
+
'--ak-effect-mesh-opacity': '0',
|
|
52
|
+
'--ak-effect-grain-opacity': '0',
|
|
53
|
+
'--ak-effect-backlight-opacity': '0',
|
|
54
|
+
},
|
|
55
|
+
darkVariables: {
|
|
56
|
+
'--ak-control-shadow': 'none',
|
|
57
|
+
'--ak-surface-shadow': 'none',
|
|
58
|
+
'--ak-surface-border-color': 'rgba(255,255,255,0.22)',
|
|
59
|
+
'--ak-press-transform': 'scale(0.99)',
|
|
60
|
+
'--ak-knob-shadow': 'none',
|
|
61
|
+
'--ak-thumb-shadow': 'none',
|
|
62
|
+
'--ak-thumb-border-w': '1px',
|
|
63
|
+
'--ak-thumb-border-color': 'rgba(255,255,255,0.22)',
|
|
64
|
+
'--ak-thumb-hover-transform': 'none',
|
|
65
|
+
'--ak-track-shadow': '0 0 0 0 transparent',
|
|
66
|
+
'--ak-effect-mesh-opacity': '0',
|
|
67
|
+
'--ak-effect-grain-opacity': '0',
|
|
68
|
+
'--ak-effect-backlight-opacity': '0',
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
id: 'glass',
|
|
73
|
+
name: 'Glassmorphic',
|
|
74
|
+
description: 'White glass — one top-left light source; sheen, rim and speculars all agree on it.',
|
|
75
|
+
radius: '0.875rem',
|
|
76
|
+
variables: {
|
|
77
|
+
// Fred's Glass v2 reference: sheen falls off from the light (125deg),
|
|
78
|
+
// rim burns hot near it and dies opposite, specular inset on the lit
|
|
79
|
+
// edge + faint bounce on the shadow side. Standard 18px thickness.
|
|
80
|
+
'--ak-surface-fill': 'rgba(255,255,255,0.11)',
|
|
81
|
+
'--ak-surface-fill-2': 'rgba(255,255,255,0.18)',
|
|
82
|
+
'--ak-surface-sheen': 'linear-gradient(125deg, rgba(255,255,255,0.20), rgba(255,255,255,0.04) 38%, rgba(255,255,255,0) 62%)',
|
|
83
|
+
'--ak-surface-blur': 'blur(18px) saturate(1.6)',
|
|
84
|
+
'--ak-surface-border-w': '0px',
|
|
85
|
+
'--ak-surface-rim': 'linear-gradient(125deg, rgba(255,255,255,0.9) 0%, rgba(255,255,255,0.25) 30%, rgba(255,255,255,0.08) 55%, rgba(255,255,255,0.18) 100%)',
|
|
86
|
+
'--ak-surface-shadow': '0 24px 48px -16px rgba(0,0,0,0.28), inset 1px 1px 1px rgba(255,255,255,0.45), inset -1px -1px 1px rgba(255,255,255,0.08)',
|
|
87
|
+
'--ak-surface-shadow-2': '0 10px 22px -10px rgba(0,0,0,0.28), inset 1px 1px 1px rgba(255,255,255,0.4)',
|
|
88
|
+
'--ak-control-shadow': '0 4px 14px rgba(15,15,20,0.10)',
|
|
89
|
+
'--ak-press-transform': 'scale(0.97)',
|
|
90
|
+
// Law 4: glass is for surfaces — small-control active parts stay FLAT
|
|
91
|
+
// SOLID. Knob/thumb = plain white with a real drop; slider track = a
|
|
92
|
+
// carved groove (dark inset + light bottom edge). Spring per the ref.
|
|
93
|
+
'--ak-knob-fill': '#ffffff',
|
|
94
|
+
'--ak-knob-fill-checked': '#ffffff',
|
|
95
|
+
'--ak-knob-shadow': '0 2px 5px rgba(0,0,0,0.4)',
|
|
96
|
+
'--ak-control-spring': 'cubic-bezier(0.34, 1.4, 0.5, 1)',
|
|
97
|
+
'--ak-thumb-fill': '#ffffff',
|
|
98
|
+
'--ak-thumb-shadow': '0 2px 5px rgba(0,0,0,0.4)',
|
|
99
|
+
'--ak-thumb-hover-transform': 'scale(1.1)',
|
|
100
|
+
'--ak-thumb-active-transform': 'scale(0.96)',
|
|
101
|
+
'--ak-track-shadow': 'inset 0 2px 3px rgba(0,0,0,0.35), inset 0 -1px 1px rgba(255,255,255,0.25)',
|
|
102
|
+
'--ak-effect-mesh-opacity': '0.18',
|
|
103
|
+
'--ak-effect-grain-opacity': '0.015',
|
|
104
|
+
'--ak-effect-backlight-opacity': '0.08',
|
|
105
|
+
},
|
|
106
|
+
darkVariables: {
|
|
107
|
+
// Smoked glass — dark material, locks in text contrast regardless of
|
|
108
|
+
// the backdrop. Dimmer sheen and rim, calmer saturation.
|
|
109
|
+
'--ak-surface-fill': 'rgba(16,17,22,0.45)',
|
|
110
|
+
'--ak-surface-fill-2': 'rgba(22,24,30,0.55)',
|
|
111
|
+
'--ak-surface-sheen': 'linear-gradient(125deg, rgba(255,255,255,0.09), rgba(255,255,255,0.02) 38%, rgba(255,255,255,0) 62%)',
|
|
112
|
+
'--ak-surface-blur': 'blur(18px) saturate(1.2)',
|
|
113
|
+
'--ak-surface-border-w': '0px',
|
|
114
|
+
'--ak-surface-rim': 'linear-gradient(125deg, rgba(255,255,255,0.35) 0%, rgba(255,255,255,0.12) 30%, rgba(255,255,255,0.04) 55%, rgba(255,255,255,0.10) 100%)',
|
|
115
|
+
'--ak-surface-shadow': '0 24px 48px -16px rgba(0,0,0,0.5), inset 1px 1px 1px rgba(255,255,255,0.18), inset -1px -1px 1px rgba(255,255,255,0.04)',
|
|
116
|
+
'--ak-surface-shadow-2': '0 10px 22px -10px rgba(0,0,0,0.5), inset 1px 1px 1px rgba(255,255,255,0.14)',
|
|
117
|
+
'--ak-control-shadow': '0 4px 14px rgba(0,0,0,0.35)',
|
|
118
|
+
'--ak-press-transform': 'scale(0.97)',
|
|
119
|
+
'--ak-knob-fill': '#ffffff',
|
|
120
|
+
'--ak-knob-fill-checked': '#ffffff',
|
|
121
|
+
'--ak-knob-shadow': '0 2px 5px rgba(0,0,0,0.55)',
|
|
122
|
+
'--ak-control-spring': 'cubic-bezier(0.34, 1.4, 0.5, 1)',
|
|
123
|
+
'--ak-thumb-fill': '#ffffff',
|
|
124
|
+
'--ak-thumb-shadow': '0 2px 5px rgba(0,0,0,0.55)',
|
|
125
|
+
'--ak-thumb-hover-transform': 'scale(1.1)',
|
|
126
|
+
'--ak-thumb-active-transform': 'scale(0.96)',
|
|
127
|
+
'--ak-track-shadow': 'inset 0 2px 3px rgba(0,0,0,0.5), inset 0 -1px 1px rgba(255,255,255,0.12)',
|
|
128
|
+
'--ak-effect-mesh-opacity': '0.14',
|
|
129
|
+
'--ak-effect-grain-opacity': '0.015',
|
|
130
|
+
'--ak-effect-backlight-opacity': '0.10',
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
id: 'brutal',
|
|
135
|
+
name: 'Neo-Brutal',
|
|
136
|
+
description: 'The house brutalism — ink borders, hard offsets, the push-into-shadow press.',
|
|
137
|
+
// House brutal keeps FRIENDLY corners (--radius-ak-brutal = 0.5rem) —
|
|
138
|
+
// hard geometry, soft radius. That contrast IS the AstralKit brutal look.
|
|
139
|
+
radius: '0.5rem',
|
|
140
|
+
variables: {
|
|
141
|
+
// The authored ak-brutal token ladder (ink #000, 4/3/6px offsets) and
|
|
142
|
+
// the three-act ak-brutal-press choreography, expressed as slots:
|
|
143
|
+
// rest 4px → hover: slide 2px into a 3px shadow → active: fully
|
|
144
|
+
// pressed, shadow collapses to zero.
|
|
145
|
+
// Control shadows use SOFTENED ink (mixed toward the page color) so a
|
|
146
|
+
// fill that matches the ink — the B&W palette's primary — still reads
|
|
147
|
+
// against its shadow (Fred's call: tone separation, not rings). Card
|
|
148
|
+
// shadows stay pure ink; faces are always lighter there.
|
|
149
|
+
'--ak-control-shadow': '4px 4px 0 0 color-mix(in srgb, #000000 72%, var(--color-ak-bg))',
|
|
150
|
+
'--ak-control-hover-transform': 'translate(2px, 2px)',
|
|
151
|
+
'--ak-control-shadow-hover': '3px 3px 0 0 color-mix(in srgb, #000000 72%, var(--color-ak-bg))',
|
|
152
|
+
'--ak-press-transform': 'translate(4px, 4px)',
|
|
153
|
+
'--ak-control-shadow-active': '0 0 0 0 #000000',
|
|
154
|
+
'--ak-surface-border-w': 'var(--border-ak-brutal)',
|
|
155
|
+
'--ak-surface-border-color': '#000000',
|
|
156
|
+
'--ak-surface-shadow': '6px 6px 0 0 #000000',
|
|
157
|
+
'--ak-weight-ui': '700',
|
|
158
|
+
'--ak-weight-ui-strong': '800',
|
|
159
|
+
'--ak-weight-heading': '800',
|
|
160
|
+
'--ak-weight-label': '700',
|
|
161
|
+
'--ak-tracking-label': '0.05em',
|
|
162
|
+
// Quiet hover = the brutal backface, bottom edge only: a THICK ink
|
|
163
|
+
// underline pushed away from the text (not a hairline text-decoration).
|
|
164
|
+
'--ak-quiet-hover-line': 'underline',
|
|
165
|
+
'--ak-quiet-hover-thickness': '3px',
|
|
166
|
+
'--ak-quiet-hover-offset': '2px',
|
|
167
|
+
'--ak-quiet-hover-bg': 'transparent',
|
|
168
|
+
'--ak-quiet-hover-color': '#000000',
|
|
169
|
+
// Brutal focus is dashed ink; nested brutal surfaces go FLAT (border
|
|
170
|
+
// only) — shadow lives at the top level, per the reference doctrine.
|
|
171
|
+
'--ak-focus-outline': '3px dashed #000000',
|
|
172
|
+
'--ak-focus-offset': '4px',
|
|
173
|
+
'--ak-surface-shadow-2': 'none',
|
|
174
|
+
// Batch-2 control slots — the squish is the juice: solid ink knob that
|
|
175
|
+
// stretches on press, square-ish thumb that tilts on hover, loud
|
|
176
|
+
// bordered tracks. Thumb shadow uses the same softened ink as controls.
|
|
177
|
+
'--ak-knob-fill': '#000000',
|
|
178
|
+
'--ak-knob-fill-checked': 'var(--color-ak-bg)',
|
|
179
|
+
'--ak-knob-shadow': 'none',
|
|
180
|
+
'--ak-knob-press': 'scaleX(1.25)',
|
|
181
|
+
'--ak-control-spring': 'cubic-bezier(0.6, 1.6, 0.4, 1)',
|
|
182
|
+
'--ak-thumb-fill': 'var(--color-ak-bg)',
|
|
183
|
+
'--ak-thumb-radius': '8px',
|
|
184
|
+
'--ak-thumb-border-w': '3px',
|
|
185
|
+
'--ak-thumb-border-color': '#000000',
|
|
186
|
+
'--ak-thumb-shadow': '2px 2px 0 0 color-mix(in srgb, #000000 72%, var(--color-ak-bg))',
|
|
187
|
+
'--ak-thumb-hover-transform': 'rotate(8deg) scale(1.08)',
|
|
188
|
+
'--ak-thumb-active-transform': 'scale(0.94)',
|
|
189
|
+
'--ak-track-shadow': '0 0 0 0 transparent',
|
|
190
|
+
'--ak-track-border-w': '2px',
|
|
191
|
+
'--ak-track-border-color': '#000000',
|
|
192
|
+
'--ak-effect-mesh-opacity': '0',
|
|
193
|
+
'--ak-effect-grain-opacity': '0',
|
|
194
|
+
'--ak-effect-backlight-opacity': '0',
|
|
195
|
+
},
|
|
196
|
+
darkVariables: {
|
|
197
|
+
// Explicit paper values — the :root substitution rule means overriding
|
|
198
|
+
// --color-ak-brutal-ink here would never reach the shadow tokens.
|
|
199
|
+
'--ak-control-shadow': '4px 4px 0 0 color-mix(in srgb, #f4f4f5 68%, var(--color-ak-bg))',
|
|
200
|
+
'--ak-control-hover-transform': 'translate(2px, 2px)',
|
|
201
|
+
'--ak-control-shadow-hover': '3px 3px 0 0 color-mix(in srgb, #f4f4f5 68%, var(--color-ak-bg))',
|
|
202
|
+
'--ak-press-transform': 'translate(4px, 4px)',
|
|
203
|
+
'--ak-control-shadow-active': '0 0 0 0 #f4f4f5',
|
|
204
|
+
'--ak-surface-border-w': 'var(--border-ak-brutal)',
|
|
205
|
+
'--ak-surface-border-color': '#f4f4f5',
|
|
206
|
+
'--ak-surface-shadow': '6px 6px 0 0 #f4f4f5',
|
|
207
|
+
'--ak-weight-ui': '700',
|
|
208
|
+
'--ak-weight-ui-strong': '800',
|
|
209
|
+
'--ak-weight-heading': '800',
|
|
210
|
+
'--ak-weight-label': '700',
|
|
211
|
+
'--ak-tracking-label': '0.05em',
|
|
212
|
+
'--ak-quiet-hover-line': 'underline',
|
|
213
|
+
'--ak-quiet-hover-thickness': '3px',
|
|
214
|
+
'--ak-quiet-hover-offset': '2px',
|
|
215
|
+
'--ak-quiet-hover-bg': 'transparent',
|
|
216
|
+
'--ak-quiet-hover-color': '#f4f4f5',
|
|
217
|
+
'--ak-focus-outline': '3px dashed #f4f4f5',
|
|
218
|
+
'--ak-focus-offset': '4px',
|
|
219
|
+
'--ak-surface-shadow-2': 'none',
|
|
220
|
+
'--ak-knob-fill': '#f4f4f5',
|
|
221
|
+
'--ak-knob-fill-checked': 'var(--color-ak-bg)',
|
|
222
|
+
'--ak-knob-shadow': 'none',
|
|
223
|
+
'--ak-knob-press': 'scaleX(1.25)',
|
|
224
|
+
'--ak-control-spring': 'cubic-bezier(0.6, 1.6, 0.4, 1)',
|
|
225
|
+
'--ak-thumb-fill': 'var(--color-ak-bg)',
|
|
226
|
+
'--ak-thumb-radius': '8px',
|
|
227
|
+
'--ak-thumb-border-w': '3px',
|
|
228
|
+
'--ak-thumb-border-color': '#f4f4f5',
|
|
229
|
+
'--ak-thumb-shadow': '2px 2px 0 0 color-mix(in srgb, #f4f4f5 68%, var(--color-ak-bg))',
|
|
230
|
+
'--ak-thumb-hover-transform': 'rotate(8deg) scale(1.08)',
|
|
231
|
+
'--ak-thumb-active-transform': 'scale(0.94)',
|
|
232
|
+
'--ak-track-shadow': '0 0 0 0 transparent',
|
|
233
|
+
'--ak-track-border-w': '2px',
|
|
234
|
+
'--ak-track-border-color': '#f4f4f5',
|
|
235
|
+
'--ak-effect-mesh-opacity': '0',
|
|
236
|
+
'--ak-effect-grain-opacity': '0',
|
|
237
|
+
'--ak-effect-backlight-opacity': '0',
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
]
|
|
241
|
+
|
|
242
|
+
export function materialToVariables(material, opts) {
|
|
243
|
+
const mode = (opts && opts.mode) || 'light'
|
|
244
|
+
return { ...(mode === 'dark' ? material.darkVariables : material.variables) }
|
|
245
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Curated 60-30-10 Theme Palettes for AstralKit Theme Builder
|
|
3
|
+
*
|
|
4
|
+
* Each palette follows the 60-30-10 rule:
|
|
5
|
+
* - 60% Dominant: background, surface (large areas)
|
|
6
|
+
* - 30% Secondary: cards, sidebar, secondary surfaces
|
|
7
|
+
* - 10% Accent: CTAs, links, highlights, primary actions
|
|
8
|
+
*
|
|
9
|
+
* Token mapping:
|
|
10
|
+
* - background: Page background (60%)
|
|
11
|
+
* - surface: Card/panel backgrounds (60% variant)
|
|
12
|
+
* - foreground: Primary text color
|
|
13
|
+
* - foregroundMuted: Secondary/body text
|
|
14
|
+
* - primary: Main accent / CTA color (10%)
|
|
15
|
+
* - secondary: Supporting color (30%)
|
|
16
|
+
* - accent: Highlight / tertiary color
|
|
17
|
+
* - border: Divider and border color
|
|
18
|
+
* - ring: Focus ring color (usually primary-based)
|
|
19
|
+
* - muted: Muted/disabled backgrounds
|
|
20
|
+
* - destructive: Error/danger color
|
|
21
|
+
*/
|
|
22
|
+
export interface ThemePalette {
|
|
23
|
+
id: string;
|
|
24
|
+
name: string;
|
|
25
|
+
description: string;
|
|
26
|
+
mode: 'light' | 'dark';
|
|
27
|
+
colors: {
|
|
28
|
+
background: string;
|
|
29
|
+
surface: string;
|
|
30
|
+
foreground: string;
|
|
31
|
+
foregroundMuted: string;
|
|
32
|
+
primary: string;
|
|
33
|
+
secondary: string;
|
|
34
|
+
accent: string;
|
|
35
|
+
/** Optional text color for filled accent elements. Defaults to computed contrast. */
|
|
36
|
+
onAccent?: string;
|
|
37
|
+
border: string;
|
|
38
|
+
ring: string;
|
|
39
|
+
muted: string;
|
|
40
|
+
destructive: string;
|
|
41
|
+
/** Optional: slider/scrubber filled-track color. Defaults to primary when omitted. */
|
|
42
|
+
sliderFill?: string;
|
|
43
|
+
/** Optional: slider thumb ring color. Defaults to paper (bg) when omitted. */
|
|
44
|
+
sliderRing?: string;
|
|
45
|
+
/** Optional: branded CTA gradient stops. Defaults are derived from primary. */
|
|
46
|
+
brandGradient?: {
|
|
47
|
+
from: string;
|
|
48
|
+
via: string;
|
|
49
|
+
to: string;
|
|
50
|
+
hoverFrom?: string;
|
|
51
|
+
hoverVia?: string;
|
|
52
|
+
hoverTo?: string;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
effects?: {
|
|
56
|
+
glowPrimary?: string;
|
|
57
|
+
glowSecondary?: string;
|
|
58
|
+
glowTertiary?: string;
|
|
59
|
+
glowWarm?: string;
|
|
60
|
+
meshBase?: string;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export type ThemeMode = ThemePalette['mode'];
|
|
64
|
+
export declare const THEME_PALETTES: ThemePalette[];
|
|
65
|
+
/**
|
|
66
|
+
* Keeps the chosen brand colors while swapping surface, text, border, and muted
|
|
67
|
+
* scaffolding to the current UI mode.
|
|
68
|
+
*/
|
|
69
|
+
export declare function resolvePaletteForMode(palette: ThemePalette, mode: ThemeMode): ThemePalette;
|
|
70
|
+
/**
|
|
71
|
+
* Maps a ThemePalette to the actual --color-ak-* CSS variables
|
|
72
|
+
* that AstralKit components consume.
|
|
73
|
+
*
|
|
74
|
+
* This is the critical bridge between our 60-30-10 palette
|
|
75
|
+
* and the component design token system.
|
|
76
|
+
*/
|
|
77
|
+
export declare function paletteToAkVariables(palette: ThemePalette, options?: {
|
|
78
|
+
mode?: ThemeMode;
|
|
79
|
+
}): Record<string, string>;
|
|
80
|
+
/**
|
|
81
|
+
* Palette authorship lint — encodes the recipe learned from curation:
|
|
82
|
+
* keepers share a near-neutral foreground, neutral light surfaces, and a
|
|
83
|
+
* mid-luminance primary (or an explicit accent split for light primaries).
|
|
84
|
+
* Returns human-readable warnings; empty array = palette is well-formed.
|
|
85
|
+
*/
|
|
86
|
+
export declare function validatePalette(palette: ThemePalette): string[];
|
|
87
|
+
/**
|
|
88
|
+
* Generates CSS :root block from a palette using the ak variable names.
|
|
89
|
+
*/
|
|
90
|
+
export declare function paletteToCSS(palette: ThemePalette): string;
|