@adea-ai/ui 0.28.0 → 0.29.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.
@@ -0,0 +1,245 @@
1
+ /**
2
+ * The versioned client appearance preference (Dev Runtime spec,
3
+ * "Appearance and App Library"). Stored as one JSON document; the legacy
4
+ * single `theme` key migrates into it without deleting the old value.
5
+ */
6
+ export type AppearancePreferencesV2 = Readonly<{
7
+ version: 2;
8
+ mode: AppearanceMode;
9
+ lightThemeId: string;
10
+ darkThemeId: string;
11
+ /** `'theme'`, a built-in preset id, or a validated `#rrggbb` color. */
12
+ accent: 'theme' | string;
13
+ surface: 'opaque' | 'frosted' | 'translucent';
14
+ reduceTransparency: boolean;
15
+ }>;
16
+ export type AppearanceMode = 'system' | 'light' | 'dark';
17
+ export type ResolvedAppearance = 'light' | 'dark';
18
+ export type SurfacePreference = 'opaque' | 'frosted' | 'translucent';
19
+ export declare const APPEARANCE_STORAGE_KEY = "appearance";
20
+ /** The pre-#425 key. Migration reads it and never deletes it. */
21
+ export declare const LEGACY_THEME_STORAGE_KEY = "theme";
22
+ export declare const DARK_QUERY = "(prefers-color-scheme: dark)";
23
+ export declare const REDUCED_TRANSPARENCY_QUERY = "(prefers-reduced-transparency: reduce)";
24
+ export declare const defaultAppearancePreferences: AppearancePreferencesV2;
25
+ /**
26
+ * Combine the user's choice with the OS state. A pinned mode ignores the OS;
27
+ * `system` follows it. (Zeron `resolve`.)
28
+ */
29
+ export declare function resolveAppearanceMode(mode: AppearanceMode, system: ResolvedAppearance): ResolvedAppearance;
30
+ export type RgbColor = Readonly<{
31
+ r: number;
32
+ g: number;
33
+ b: number;
34
+ a: number;
35
+ }>;
36
+ export declare class ColorParseError extends Error {
37
+ constructor();
38
+ }
39
+ /** Parse a hex color. Returns `undefined` for anything unsupported. */
40
+ export declare function parseColor(value: string): RgbColor | undefined;
41
+ export declare function colorToHex(color: RgbColor): string;
42
+ /** WCAG contrast ratio between two colors. Alpha composites over the background first. */
43
+ export declare function contrastRatio(foreground: RgbColor | string, background: RgbColor | string): number;
44
+ export type AccentPreset = Readonly<{
45
+ id: string;
46
+ label: string;
47
+ dark: string;
48
+ light: string;
49
+ }>;
50
+ export declare const accentPresets: readonly AccentPreset[];
51
+ /**
52
+ * Normalize a custom accent color against a variant background: unparseable
53
+ * input is rejected (`undefined`), and any accepted color is raised to the
54
+ * 3:1 interaction minimum so an accent can never ship unreadable.
55
+ */
56
+ export declare function normalizeAccentValue(value: string, background: string): string | undefined;
57
+ export declare function accentPresetById(id: string): AccentPreset | undefined;
58
+ export type AccentRoles = Readonly<{
59
+ /** Interactive primary. */
60
+ primary: string;
61
+ /** Text drawn on `primary`-filled controls; ≥ 4.5:1 against it. */
62
+ onPrimary: string;
63
+ /** Hover/press emphasis derived from the primary. */
64
+ strong: string;
65
+ /** Focus ring color. */
66
+ ring: string;
67
+ /** False when the selection is the variant's own accent and no role should be overridden. */
68
+ overrides: boolean;
69
+ }>;
70
+ /**
71
+ * Derive the accent roles for a selection against a variant. `'theme'` keeps
72
+ * the variant's own accent; presets and custom colors are normalized to the
73
+ * 3:1 interaction minimum (Zeron `AccentRoles::derive`, thresholds preserved).
74
+ */
75
+ export declare function deriveAccentRoles(selection: string, variant: ThemeVariant): AccentRoles;
76
+ export type EffectiveSurface = 'opaque' | 'frosted' | 'translucent';
77
+ export declare function resolveSurface(preference: SurfacePreference, environment: Readonly<{
78
+ osReducedTransparency: boolean;
79
+ userReducedTransparency: boolean;
80
+ nativeTranslucency: boolean;
81
+ }>): EffectiveSurface;
82
+ export type ThemeTerminalPalette = Readonly<{
83
+ background: string;
84
+ foreground: string;
85
+ cursor: string;
86
+ selection: string;
87
+ /** The 16 xterm ANSI slots, in protocol order. */
88
+ ansi: readonly string[];
89
+ }>;
90
+ export type ThemeEditorRoles = Readonly<{
91
+ keyword: string;
92
+ string: string;
93
+ number: string;
94
+ comment: string;
95
+ function: string;
96
+ variable: string;
97
+ type: string;
98
+ tag: string;
99
+ attribute: string;
100
+ operator: string;
101
+ heading: string;
102
+ link: string;
103
+ diffAdd: string;
104
+ diffDelete: string;
105
+ diffHunk: string;
106
+ searchMatch: string;
107
+ }>;
108
+ export type ThemeChartRoles = Readonly<{
109
+ chart1: string;
110
+ chart2: string;
111
+ chart3: string;
112
+ chart4: string;
113
+ chart5: string;
114
+ chart6: string;
115
+ }>;
116
+ export type ThemeColors = Readonly<{
117
+ background: string;
118
+ foreground: string;
119
+ card: string;
120
+ cardForeground: string;
121
+ popover: string;
122
+ popoverForeground: string;
123
+ primary: string;
124
+ primaryForeground: string;
125
+ secondary: string;
126
+ secondaryForeground: string;
127
+ muted: string;
128
+ mutedForeground: string;
129
+ accent: string;
130
+ accentForeground: string;
131
+ destructive: string;
132
+ success: string;
133
+ border: string;
134
+ input: string;
135
+ ring: string;
136
+ }>;
137
+ export type ThemeVariant = Readonly<{
138
+ id: string;
139
+ familyId: string;
140
+ familyName: string;
141
+ name: string;
142
+ appearance: ResolvedAppearance;
143
+ colors: ThemeColors;
144
+ terminal: ThemeTerminalPalette;
145
+ editor: ThemeEditorRoles;
146
+ charts: ThemeChartRoles;
147
+ }>;
148
+ /**
149
+ * The independent per-appearance theme selection (Zeron `ThemeSelection`,
150
+ * carrying the V2 preference's field names).
151
+ */
152
+ export type ThemeSelection = Readonly<{
153
+ lightThemeId: string;
154
+ darkThemeId: string;
155
+ }>;
156
+ export declare function themeSelectionVariantId(selection: ThemeSelection, appearance: ResolvedAppearance): string;
157
+ export type ValidationIssue = Readonly<{
158
+ variantId: string;
159
+ severity: 'error' | 'warning';
160
+ message: string;
161
+ }>;
162
+ /**
163
+ * Registry validation, ported from Zeron `ThemeRegistry::validate`: core text
164
+ * and muted text must reach 4.5:1, the accent 3:1, on-accent 4.5:1, the
165
+ * terminal foreground 4.5:1, and every chromatic ANSI slot 3:1 (slots 0 and 8
166
+ * are structural black/dim colors). Provenance completeness is a Zeron
167
+ * library concept; M12 ships only built-ins, so the structural check here is
168
+ * id/non-empty-color integrity.
169
+ */
170
+ export declare function validateThemeRegistry(registry: readonly ThemeVariant[]): ValidationIssue[];
171
+ /**
172
+ * Resolve the variant for a selection, falling back deterministically to the
173
+ * default variant of the same appearance when the stored id is missing or
174
+ * broken — a corrupt preference degrades the palette, never the UI.
175
+ * (Zeron `ThemeRegistry::resolve`.)
176
+ */
177
+ export declare function resolveThemeVariant(registry: readonly ThemeVariant[], selection: ThemeSelection, appearance: ResolvedAppearance): ThemeVariant;
178
+ /** The `adea-light`/`adea-dark` entries mirror `styles/theme.css`. */
179
+ export declare const builtinThemeRegistry: readonly ThemeVariant[];
180
+ export type NormalizedPreferences = Readonly<{
181
+ /** The strict v2 document, with every unknown field corrected to defaults. */
182
+ value: AppearancePreferencesV2;
183
+ /**
184
+ * The raw stored document when it was not a valid v2 record. Retained so a
185
+ * future version (or a repaired write) never loses the user's data.
186
+ */
187
+ retainedRaw?: unknown;
188
+ }>;
189
+ /**
190
+ * Parse a stored appearance document. Anything that is not a strict version-2
191
+ * record falls back to the defaults and keeps the raw value for retention;
192
+ * individual unknown values inside a v2 record are corrected field by field.
193
+ */
194
+ export declare function normalizeAppearancePreferences(raw: unknown): NormalizedPreferences;
195
+ /** The legacy single-key preference, mapped into v2 during migration. */
196
+ export declare function migrateLegacyThemeValue(stored: string | null): AppearancePreferencesV2 | undefined;
197
+ type AppearanceStorage = Pick<Storage, 'getItem' | 'setItem' | 'removeItem'>;
198
+ /**
199
+ * Read the appearance preferences: the v2 key first, then the legacy `theme`
200
+ * key, then defaults. Storage failures degrade to defaults like every other
201
+ * blocked-storage consumer.
202
+ */
203
+ export declare function readAppearancePreferences(storage: AppearanceStorage | undefined): AppearancePreferencesV2;
204
+ export declare function writeAppearancePreferences(storage: AppearanceStorage | undefined, preferences: AppearancePreferencesV2): void;
205
+ export type ResolvedAppearanceState = Readonly<{
206
+ resolvedMode: ResolvedAppearance;
207
+ variant: ThemeVariant;
208
+ accent: AccentRoles;
209
+ effectiveSurface: EffectiveSurface;
210
+ reduceTransparencyActive: boolean;
211
+ }>;
212
+ /** Resolve preferences against the environment into the applied document state. */
213
+ export declare function resolveAppearanceState(preferences: AppearancePreferencesV2, environment: Readonly<{
214
+ systemAppearance: ResolvedAppearance;
215
+ osReducedTransparency: boolean;
216
+ nativeTranslucency: boolean;
217
+ }>, registry?: readonly ThemeVariant[]): ResolvedAppearanceState;
218
+ /**
219
+ * The custom properties a non-default variant owns, as a flat map. This one
220
+ * mapping feeds both the live provider and the pre-paint no-flash script, so
221
+ * a restored first paint and a later live switch cannot disagree. Default
222
+ * variants return an empty map: `styles/theme.css` declares those tokens.
223
+ */
224
+ export declare function flatVariantTokens(variant: ThemeVariant): Record<string, string>;
225
+ /**
226
+ * Apply a resolved state to a document: the `dark` class and color scheme for
227
+ * the palette, the diagnostic data attributes, the accent role overrides, and
228
+ * the resolved variant's semantic tokens (including terminal ANSI and editor
229
+ * roles). CSS custom properties cascade, so terminals and editors update live
230
+ * without remounting.
231
+ *
232
+ * The default `adea-light`/`adea-dark` variants skip the palette override —
233
+ * `styles/theme.css` declares those tokens already, and leaving them CSS-owned
234
+ * keeps first paint byte-identical to the pre-#425 app.
235
+ */
236
+ export declare function applyAppearanceToDocument(document: Document, state: ResolvedAppearanceState): void;
237
+ /**
238
+ * The no-flash preload script rendered in the document head. It re-resolves
239
+ * the stored (or legacy) preference against the OS before first paint and
240
+ * applies the same palette state the provider would, so hydration never shows
241
+ * the wrong palette. Accent overrides land with the provider: they decorate
242
+ * the resolved palette and cannot produce a wrong-palette flash.
243
+ */
244
+ export declare function appearanceThemeScript(): string;
245
+ export {};