@brimveyn/aimux-config 0.5.3 → 0.5.6
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/package.json +1 -1
- package/src/actions.ts +58 -0
- package/src/defaults.ts +3 -0
- package/src/index.ts +21 -31
- package/src/resolver.ts +1 -1
- package/src/tui/index.ts +5 -0
- package/src/tui/registry.ts +95 -0
- package/src/tui/resolve.ts +156 -0
- package/src/tui/shiki.ts +149 -0
- package/src/tui/themes/aimux.json +110 -0
- package/src/tui/themes/aura.json +69 -0
- package/src/tui/themes/ayu.json +80 -0
- package/src/tui/themes/carbonfox.json +248 -0
- package/src/tui/themes/catppuccin-frappe.json +230 -0
- package/src/tui/themes/catppuccin-macchiato.json +230 -0
- package/src/tui/themes/catppuccin.json +112 -0
- package/src/tui/themes/cobalt2.json +225 -0
- package/src/tui/themes/cursor.json +249 -0
- package/src/tui/themes/dracula.json +219 -0
- package/src/tui/themes/everforest.json +241 -0
- package/src/tui/themes/flexoki.json +237 -0
- package/src/tui/themes/github.json +233 -0
- package/src/tui/themes/gruvbox.json +242 -0
- package/src/tui/themes/kanagawa.json +77 -0
- package/src/tui/themes/lucent-orng.json +234 -0
- package/src/tui/themes/material.json +235 -0
- package/src/tui/themes/matrix.json +77 -0
- package/src/tui/themes/mercury.json +252 -0
- package/src/tui/themes/monokai.json +221 -0
- package/src/tui/themes/nightowl.json +221 -0
- package/src/tui/themes/nord.json +223 -0
- package/src/tui/themes/one-dark.json +84 -0
- package/src/tui/themes/opencode.json +245 -0
- package/src/tui/themes/orng.json +249 -0
- package/src/tui/themes/osaka-jade.json +93 -0
- package/src/tui/themes/palenight.json +222 -0
- package/src/tui/themes/rosepine.json +234 -0
- package/src/tui/themes/solarized.json +223 -0
- package/src/tui/themes/synthwave84.json +226 -0
- package/src/tui/themes/tokyonight.json +243 -0
- package/src/tui/themes/vercel.json +245 -0
- package/src/tui/themes/vesper.json +218 -0
- package/src/tui/themes/zenburn.json +223 -0
- package/src/tui/tokens.ts +111 -0
- package/src/tui/types.ts +30 -0
- package/src/types.ts +9 -35
- package/src/house-themes.ts +0 -55
- package/src/neutral-scale.ts +0 -75
- package/src/oklch.ts +0 -164
- package/src/palette-to-shiki.ts +0 -134
- package/src/palette-utils.ts +0 -130
- package/src/themes/opencode.ts +0 -1460
- package/src/themes.ts +0 -30
package/src/house-themes.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
// Hand-curated aimux house palettes. The opencode-style semantic palette
|
|
2
|
-
// drives both UI chrome and the runtime-generated Shiki theme — see
|
|
3
|
-
// `palette-to-shiki.ts`.
|
|
4
|
-
/* eslint-disable perfectionist/sort-objects */
|
|
5
|
-
|
|
6
|
-
import type { AimuxPalette, AimuxTheme } from './types'
|
|
7
|
-
|
|
8
|
-
const AIMUX_DARK_PALETTE: AimuxPalette = {
|
|
9
|
-
neutral: '#11151b',
|
|
10
|
-
ink: '#edf4ff',
|
|
11
|
-
primary: '#7cd1b8',
|
|
12
|
-
success: '#8bd5ca',
|
|
13
|
-
warning: '#f6c177',
|
|
14
|
-
error: '#f38ba8',
|
|
15
|
-
info: '#7cb3ff',
|
|
16
|
-
accent: '#c4a7e7',
|
|
17
|
-
interactive: '#1f3344',
|
|
18
|
-
diffAdd: '#1e3d2b',
|
|
19
|
-
diffDelete: '#3b1e27',
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const AIMUX_LIGHT_PALETTE: AimuxPalette = {
|
|
23
|
-
neutral: '#f7f9fc',
|
|
24
|
-
ink: '#11151b',
|
|
25
|
-
primary: '#1f8a72',
|
|
26
|
-
success: '#2e9a83',
|
|
27
|
-
warning: '#b8770f',
|
|
28
|
-
error: '#c43b58',
|
|
29
|
-
info: '#2e6cc1',
|
|
30
|
-
accent: '#7d57b8',
|
|
31
|
-
interactive: '#dbe6f0',
|
|
32
|
-
diffAdd: '#d4ebd9',
|
|
33
|
-
diffDelete: '#f0d6dc',
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export const HOUSE_THEMES: Record<string, AimuxTheme> = {
|
|
37
|
-
'aimux-dark': {
|
|
38
|
-
name: 'aimux',
|
|
39
|
-
mode: 'dark',
|
|
40
|
-
displayName: 'Aimux Dark',
|
|
41
|
-
palette: AIMUX_DARK_PALETTE,
|
|
42
|
-
fg: AIMUX_DARK_PALETTE.ink,
|
|
43
|
-
bg: AIMUX_DARK_PALETTE.neutral,
|
|
44
|
-
},
|
|
45
|
-
'aimux-light': {
|
|
46
|
-
name: 'aimux',
|
|
47
|
-
mode: 'light',
|
|
48
|
-
displayName: 'Aimux Light',
|
|
49
|
-
palette: AIMUX_LIGHT_PALETTE,
|
|
50
|
-
fg: AIMUX_LIGHT_PALETTE.ink,
|
|
51
|
-
bg: AIMUX_LIGHT_PALETTE.neutral,
|
|
52
|
-
},
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export const HOUSE_THEME_IDS: string[] = ['aimux-dark', 'aimux-light']
|
package/src/neutral-scale.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
// Port (minimal) of sst/opencode's generateNeutralScale + generateNeutralAlphaScale
|
|
2
|
-
// from packages/ui/src/theme/resolve.ts. Only the `ink`-provided branch of
|
|
3
|
-
// generateNeutralScale is needed — every aimux theme supplies an `ink` seed.
|
|
4
|
-
|
|
5
|
-
import { blend, hexToOklch, mixColors, oklchToHex } from './oklch'
|
|
6
|
-
|
|
7
|
-
function clamp(v: number, min: number, max: number): number {
|
|
8
|
-
return Math.max(min, Math.min(max, v))
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export type NeutralScale = readonly [
|
|
12
|
-
string,
|
|
13
|
-
string,
|
|
14
|
-
string,
|
|
15
|
-
string,
|
|
16
|
-
string,
|
|
17
|
-
string,
|
|
18
|
-
string,
|
|
19
|
-
string,
|
|
20
|
-
string,
|
|
21
|
-
string,
|
|
22
|
-
string,
|
|
23
|
-
string,
|
|
24
|
-
]
|
|
25
|
-
|
|
26
|
-
function pickDarkBg(base: { c: number; h: number; l: number }): string {
|
|
27
|
-
const tone = clamp(0.19 + Math.max(0, base.l - 0.12) * 0.33 + base.c * 1.95, 0.17, 0.27)
|
|
28
|
-
return oklchToHex({
|
|
29
|
-
c: base.c * Math.max(0, 1 - tone * 0.12),
|
|
30
|
-
h: base.h,
|
|
31
|
-
l: base.l * (1 - tone),
|
|
32
|
-
})
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function pickLightBg(base: { c: number; h: number; l: number }): string {
|
|
36
|
-
const tone =
|
|
37
|
-
base.l < 0.82 ? 0.86 : clamp(0.1 + base.c * 3.2 + Math.max(0, 0.95 - base.l) * 0.35, 0.1, 0.28)
|
|
38
|
-
return oklchToHex({
|
|
39
|
-
c: base.c * Math.max(0, 1 - tone),
|
|
40
|
-
h: base.h,
|
|
41
|
-
l: base.l + (1 - base.l) * tone,
|
|
42
|
-
})
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Produce a 12-step neutral scale from a palette seed.
|
|
47
|
-
*
|
|
48
|
-
* Step 0 is the effective app background (`palette.neutral` is treated as a
|
|
49
|
-
* seed, not a direct hex). Step 11 lands close to `ink`. Intermediate steps
|
|
50
|
-
* mix the computed bg toward ink using opencode's fixed lightness stops.
|
|
51
|
-
*/
|
|
52
|
-
export function generateNeutralScale(seed: string, isDark: boolean, ink: string): NeutralScale {
|
|
53
|
-
const base = hexToOklch(seed)
|
|
54
|
-
const bg = isDark ? pickDarkBg(base) : pickLightBg(base)
|
|
55
|
-
|
|
56
|
-
const steps = isDark
|
|
57
|
-
? [0, 0.018, 0.039, 0.064, 0.097, 0.143, 0.212, 0.31, 0.46, 0.649, 0.845, 0.984]
|
|
58
|
-
: [0, 0.022, 0.042, 0.068, 0.102, 0.146, 0.208, 0.296, 0.432, 0.61, 0.81, 0.965]
|
|
59
|
-
|
|
60
|
-
return steps.map((step) => mixColors(bg, ink, step)) as unknown as NeutralScale
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* 12-step alpha overlay scale blending ink → bg. Used for surface-base /
|
|
65
|
-
* surface-hover / border-base tokens so they stay consistent with the
|
|
66
|
-
* computed bg above.
|
|
67
|
-
*/
|
|
68
|
-
export function generateNeutralAlphaScale(neutral: NeutralScale, isDark: boolean): NeutralScale {
|
|
69
|
-
const alphas = isDark
|
|
70
|
-
? [0.038, 0.066, 0.1, 0.142, 0.19, 0.252, 0.334, 0.446, 0.58, 0.718, 0.854, 0.985]
|
|
71
|
-
: [0.03, 0.06, 0.1, 0.145, 0.2, 0.265, 0.35, 0.47, 0.61, 0.74, 0.86, 0.97]
|
|
72
|
-
const ink = neutral[11]
|
|
73
|
-
const bg = neutral[0]
|
|
74
|
-
return alphas.map((alpha) => blend(ink, bg, alpha)) as unknown as NeutralScale
|
|
75
|
-
}
|
package/src/oklch.ts
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
// OKLCH color helpers. Ported (and trimmed) from sst/opencode:
|
|
2
|
-
// packages/ui/src/theme/color.ts — used by neutral-scale.ts to derive
|
|
3
|
-
// aimux surface tokens from a palette seed.
|
|
4
|
-
|
|
5
|
-
export interface OklchColor {
|
|
6
|
-
l: number
|
|
7
|
-
c: number
|
|
8
|
-
h: number
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function clamp(v: number, min: number, max: number): number {
|
|
12
|
-
return Math.max(min, Math.min(max, v))
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function hue(v: number): number {
|
|
16
|
-
return ((v % 360) + 360) % 360
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function hexToRgb(hex: string): { r: number; g: number; b: number } {
|
|
20
|
-
const h = hex.replace('#', '')
|
|
21
|
-
const full =
|
|
22
|
-
h.length === 3 || h.length === 4
|
|
23
|
-
? h
|
|
24
|
-
.split('')
|
|
25
|
-
.map((c) => c + c)
|
|
26
|
-
.join('')
|
|
27
|
-
: h
|
|
28
|
-
const rgb = full.length === 8 ? full.slice(0, 6) : full
|
|
29
|
-
const num = parseInt(rgb, 16)
|
|
30
|
-
return {
|
|
31
|
-
b: (num & 255) / 255,
|
|
32
|
-
g: ((num >> 8) & 255) / 255,
|
|
33
|
-
r: ((num >> 16) & 255) / 255,
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function rgbToHex(r: number, g: number, b: number): string {
|
|
38
|
-
const toHex = (v: number): string => {
|
|
39
|
-
const clamped = clamp(v, 0, 1)
|
|
40
|
-
const int = Math.round(clamped * 255)
|
|
41
|
-
return int.toString(16).padStart(2, '0')
|
|
42
|
-
}
|
|
43
|
-
return `#${toHex(r)}${toHex(g)}${toHex(b)}`
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function srgbToLinear(c: number): number {
|
|
47
|
-
if (c <= 0.04045) return c / 12.92
|
|
48
|
-
return Math.pow((c + 0.055) / 1.055, 2.4)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function linearToSrgb(c: number): number {
|
|
52
|
-
if (c <= 0.0031308) return c * 12.92
|
|
53
|
-
return 1.055 * Math.pow(c, 1 / 2.4) - 0.055
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export function rgbToOklch(r: number, g: number, b: number): OklchColor {
|
|
57
|
-
const lr = srgbToLinear(r)
|
|
58
|
-
const lg = srgbToLinear(g)
|
|
59
|
-
const lb = srgbToLinear(b)
|
|
60
|
-
|
|
61
|
-
const lLong = 0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb
|
|
62
|
-
const mLong = 0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb
|
|
63
|
-
const sLong = 0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb
|
|
64
|
-
|
|
65
|
-
const lCbrt = Math.cbrt(lLong)
|
|
66
|
-
const mCbrt = Math.cbrt(mLong)
|
|
67
|
-
const sCbrt = Math.cbrt(sLong)
|
|
68
|
-
|
|
69
|
-
const L = 0.2104542553 * lCbrt + 0.793617785 * mCbrt - 0.0040720468 * sCbrt
|
|
70
|
-
const a = 1.9779984951 * lCbrt - 2.428592205 * mCbrt + 0.4505937099 * sCbrt
|
|
71
|
-
const bOk = 0.0259040371 * lCbrt + 0.7827717662 * mCbrt - 0.808675766 * sCbrt
|
|
72
|
-
|
|
73
|
-
const C = Math.sqrt(a * a + bOk * bOk)
|
|
74
|
-
let H = Math.atan2(bOk, a) * (180 / Math.PI)
|
|
75
|
-
if (H < 0) H += 360
|
|
76
|
-
|
|
77
|
-
return { c: C, h: H, l: L }
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export function oklchToRgb(ok: OklchColor): { r: number; g: number; b: number } {
|
|
81
|
-
const { c: C, h: H, l: L } = ok
|
|
82
|
-
const a = C * Math.cos((H * Math.PI) / 180)
|
|
83
|
-
const b = C * Math.sin((H * Math.PI) / 180)
|
|
84
|
-
|
|
85
|
-
const lLin = L + 0.3963377774 * a + 0.2158037573 * b
|
|
86
|
-
const mLin = L - 0.1055613458 * a - 0.0638541728 * b
|
|
87
|
-
const sLin = L - 0.0894841775 * a - 1.291485548 * b
|
|
88
|
-
|
|
89
|
-
const l3 = lLin * lLin * lLin
|
|
90
|
-
const m3 = mLin * mLin * mLin
|
|
91
|
-
const s3 = sLin * sLin * sLin
|
|
92
|
-
|
|
93
|
-
const lr = 4.0767416621 * l3 - 3.3077115913 * m3 + 0.2309699292 * s3
|
|
94
|
-
const lg = -1.2684380046 * l3 + 2.6097574011 * m3 - 0.3413193965 * s3
|
|
95
|
-
const lb = -0.0041960863 * l3 - 0.7034186147 * m3 + 1.707614701 * s3
|
|
96
|
-
|
|
97
|
-
return { b: linearToSrgb(lb), g: linearToSrgb(lg), r: linearToSrgb(lr) }
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export function hexToOklch(hex: string): OklchColor {
|
|
101
|
-
const { b, g, r } = hexToRgb(hex)
|
|
102
|
-
return rgbToOklch(r, g, b)
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Pull an out-of-gamut OKLCH into sRGB by shrinking chroma.
|
|
106
|
-
export function fitOklch(ok: OklchColor): OklchColor {
|
|
107
|
-
const base: OklchColor = {
|
|
108
|
-
c: Math.max(0, ok.c),
|
|
109
|
-
h: hue(ok.h),
|
|
110
|
-
l: clamp(ok.l, 0, 1),
|
|
111
|
-
}
|
|
112
|
-
const rgb = oklchToRgb(base)
|
|
113
|
-
if (rgb.r >= 0 && rgb.r <= 1 && rgb.g >= 0 && rgb.g <= 1 && rgb.b >= 0 && rgb.b <= 1) {
|
|
114
|
-
return base
|
|
115
|
-
}
|
|
116
|
-
let c = base.c
|
|
117
|
-
for (let i = 0; i < 24; i++) {
|
|
118
|
-
c *= 0.9
|
|
119
|
-
const next: OklchColor = { ...base, c }
|
|
120
|
-
const out = oklchToRgb(next)
|
|
121
|
-
if (out.r >= 0 && out.r <= 1 && out.g >= 0 && out.g <= 1 && out.b >= 0 && out.b <= 1) {
|
|
122
|
-
return next
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
return { ...base, c: 0 }
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export function oklchToHex(ok: OklchColor): string {
|
|
129
|
-
const { b, g, r } = oklchToRgb(fitOklch(ok))
|
|
130
|
-
return rgbToHex(r, g, b)
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/** OKLCH-space mix. t=0 returns `a`, t=1 returns `b`. Uses shortest hue arc. */
|
|
134
|
-
export function mixColors(a: string, b: string, t: number): string {
|
|
135
|
-
const ca = hexToOklch(a)
|
|
136
|
-
const cb = hexToOklch(b)
|
|
137
|
-
const delta = ((((cb.h - ca.h) % 360) + 540) % 360) - 180
|
|
138
|
-
return oklchToHex({
|
|
139
|
-
c: ca.c + (cb.c - ca.c) * t,
|
|
140
|
-
h: ca.h + delta * t,
|
|
141
|
-
l: ca.l + (cb.l - ca.l) * t,
|
|
142
|
-
})
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/** OKLCH shift: additive L, multiplicative C, additive H (degrees). */
|
|
146
|
-
export function shift(color: string, value: { l?: number; c?: number; h?: number }): string {
|
|
147
|
-
const base = hexToOklch(color)
|
|
148
|
-
return oklchToHex({
|
|
149
|
-
c: base.c * (value.c ?? 1),
|
|
150
|
-
h: base.h + (value.h ?? 0),
|
|
151
|
-
l: base.l + (value.l ?? 0),
|
|
152
|
-
})
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/** sRGB alpha blend: `color` over `background` at `alpha` opacity. */
|
|
156
|
-
export function blend(color: string, background: string, alpha: number): string {
|
|
157
|
-
const fg = hexToRgb(color)
|
|
158
|
-
const bg = hexToRgb(background)
|
|
159
|
-
return rgbToHex(
|
|
160
|
-
fg.r * alpha + bg.r * (1 - alpha),
|
|
161
|
-
fg.g * alpha + bg.g * (1 - alpha),
|
|
162
|
-
fg.b * alpha + bg.b * (1 - alpha)
|
|
163
|
-
)
|
|
164
|
-
}
|
package/src/palette-to-shiki.ts
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
// Build a Shiki ThemeRegistrationRaw from an AimuxPalette. The same palette
|
|
2
|
-
// powers the UI chrome and the diff syntax highlighter — there's no static
|
|
3
|
-
// theme JSON, so light/dark/overrides stay coherent automatically.
|
|
4
|
-
|
|
5
|
-
import type { ThemeRegistrationRaw } from 'shiki'
|
|
6
|
-
|
|
7
|
-
import type { AimuxPalette, ThemeMode } from './types'
|
|
8
|
-
|
|
9
|
-
import { accent as accentOf, muted } from './palette-utils'
|
|
10
|
-
|
|
11
|
-
export interface PaletteToShikiOptions {
|
|
12
|
-
name: string
|
|
13
|
-
mode: ThemeMode
|
|
14
|
-
palette: AimuxPalette
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function paletteToShikiTheme(opts: PaletteToShikiOptions): ThemeRegistrationRaw {
|
|
18
|
-
const { mode, name, palette: p } = opts
|
|
19
|
-
const m = muted(p)
|
|
20
|
-
const a = accentOf(p)
|
|
21
|
-
|
|
22
|
-
return {
|
|
23
|
-
bg: p.neutral,
|
|
24
|
-
colors: {
|
|
25
|
-
'editor.background': p.neutral,
|
|
26
|
-
'editor.foreground': p.ink,
|
|
27
|
-
},
|
|
28
|
-
fg: p.ink,
|
|
29
|
-
name,
|
|
30
|
-
settings: [
|
|
31
|
-
{ settings: { background: p.neutral, foreground: p.ink } },
|
|
32
|
-
{
|
|
33
|
-
scope: ['comment', 'punctuation.definition.comment'],
|
|
34
|
-
settings: { fontStyle: 'italic', foreground: m },
|
|
35
|
-
},
|
|
36
|
-
{ scope: ['comment.documentation'], settings: { fontStyle: 'italic', foreground: m } },
|
|
37
|
-
{
|
|
38
|
-
scope: ['string', 'string.quoted', 'string.template'],
|
|
39
|
-
settings: { foreground: p.warning },
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
scope: ['string.regexp', 'string.escape', 'constant.character.escape'],
|
|
43
|
-
settings: { foreground: a },
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
scope: [
|
|
47
|
-
'constant.numeric',
|
|
48
|
-
'constant.language',
|
|
49
|
-
'constant.language.boolean',
|
|
50
|
-
'constant.character',
|
|
51
|
-
'constant.other',
|
|
52
|
-
'support.constant',
|
|
53
|
-
],
|
|
54
|
-
settings: { foreground: p.error },
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
scope: ['keyword', 'keyword.control', 'keyword.operator.new', 'keyword.other'],
|
|
58
|
-
settings: { fontStyle: 'bold', foreground: a },
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
scope: ['storage', 'storage.type', 'storage.modifier'],
|
|
62
|
-
settings: { fontStyle: 'bold', foreground: a },
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
scope: ['keyword.operator', 'punctuation', 'meta.brace', 'punctuation.separator'],
|
|
66
|
-
settings: { foreground: m },
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
scope: [
|
|
70
|
-
'entity.name.function',
|
|
71
|
-
'support.function',
|
|
72
|
-
'meta.function-call',
|
|
73
|
-
'entity.name.function.member',
|
|
74
|
-
],
|
|
75
|
-
settings: { foreground: p.success },
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
scope: [
|
|
79
|
-
'entity.name.type',
|
|
80
|
-
'support.type',
|
|
81
|
-
'support.class',
|
|
82
|
-
'entity.name.class',
|
|
83
|
-
'entity.name.interface',
|
|
84
|
-
'entity.name.namespace',
|
|
85
|
-
'entity.name.type.enum',
|
|
86
|
-
'entity.name.type.alias',
|
|
87
|
-
'entity.name.tag.jsx',
|
|
88
|
-
'support.class.component',
|
|
89
|
-
],
|
|
90
|
-
settings: { fontStyle: 'italic', foreground: p.primary },
|
|
91
|
-
},
|
|
92
|
-
{ scope: ['variable', 'meta.variable'], settings: { foreground: p.ink } },
|
|
93
|
-
{
|
|
94
|
-
scope: ['variable.parameter', 'meta.function.parameters'],
|
|
95
|
-
settings: { fontStyle: 'italic', foreground: p.ink },
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
scope: ['variable.other.property', 'variable.other.member', 'meta.object-literal.key'],
|
|
99
|
-
settings: { foreground: p.primary },
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
scope: ['variable.language', 'variable.language.this'],
|
|
103
|
-
settings: { fontStyle: 'italic', foreground: p.error },
|
|
104
|
-
},
|
|
105
|
-
{ scope: ['entity.name.tag', 'meta.tag'], settings: { foreground: p.error } },
|
|
106
|
-
{
|
|
107
|
-
scope: ['entity.other.attribute-name'],
|
|
108
|
-
settings: { fontStyle: 'italic', foreground: p.warning },
|
|
109
|
-
},
|
|
110
|
-
// Markdown
|
|
111
|
-
{ scope: ['markup.heading'], settings: { fontStyle: 'bold', foreground: p.primary } },
|
|
112
|
-
{ scope: ['markup.bold'], settings: { fontStyle: 'bold', foreground: p.ink } },
|
|
113
|
-
{ scope: ['markup.italic'], settings: { fontStyle: 'italic', foreground: p.ink } },
|
|
114
|
-
{
|
|
115
|
-
scope: ['markup.underline.link', 'markup.inline.raw', 'markup.raw'],
|
|
116
|
-
settings: { foreground: p.success },
|
|
117
|
-
},
|
|
118
|
-
{ scope: ['markup.list'], settings: { foreground: a } },
|
|
119
|
-
{ scope: ['markup.quote'], settings: { fontStyle: 'italic', foreground: m } },
|
|
120
|
-
// Diff
|
|
121
|
-
{
|
|
122
|
-
scope: ['markup.inserted', 'meta.diff.header.to-file'],
|
|
123
|
-
settings: { foreground: p.success },
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
scope: ['markup.deleted', 'meta.diff.header.from-file'],
|
|
127
|
-
settings: { foreground: p.error },
|
|
128
|
-
},
|
|
129
|
-
{ scope: ['markup.changed'], settings: { foreground: p.warning } },
|
|
130
|
-
{ scope: ['meta.diff.range'], settings: { foreground: a } },
|
|
131
|
-
],
|
|
132
|
-
type: mode,
|
|
133
|
-
}
|
|
134
|
-
}
|
package/src/palette-utils.ts
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import type { AimuxPalette, ThemeMode } from './types'
|
|
2
|
-
|
|
3
|
-
import { generateNeutralAlphaScale, generateNeutralScale } from './neutral-scale'
|
|
4
|
-
import { blend } from './oklch'
|
|
5
|
-
|
|
6
|
-
function stripAlpha(hex: string): string {
|
|
7
|
-
if (hex.length === 9) return hex.slice(0, 7)
|
|
8
|
-
if (hex.length === 5) return hex.slice(0, 4)
|
|
9
|
-
return hex
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function expand3(hex: string): string {
|
|
13
|
-
if (hex.length === 4) return `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}`
|
|
14
|
-
return hex
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function parseHex(hex: string): { b: number; g: number; r: number } {
|
|
18
|
-
const clean = expand3(stripAlpha(hex))
|
|
19
|
-
return {
|
|
20
|
-
b: parseInt(clean.slice(5, 7), 16),
|
|
21
|
-
g: parseInt(clean.slice(3, 5), 16),
|
|
22
|
-
r: parseInt(clean.slice(1, 3), 16),
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function toHex({ b, g, r }: { b: number; g: number; r: number }): string {
|
|
27
|
-
const clamp = (n: number): number => Math.max(0, Math.min(255, Math.round(n)))
|
|
28
|
-
const h = (n: number): string => clamp(n).toString(16).padStart(2, '0')
|
|
29
|
-
return `#${h(r)}${h(g)}${h(b)}`
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/** Linearly mix two hex colors. `t=0` returns `a`, `t=1` returns `b`. */
|
|
33
|
-
export function mix(a: string, b: string, t: number): string {
|
|
34
|
-
const ca = parseHex(a)
|
|
35
|
-
const cb = parseHex(b)
|
|
36
|
-
return toHex({
|
|
37
|
-
b: ca.b + (cb.b - ca.b) * t,
|
|
38
|
-
g: ca.g + (cb.g - ca.g) * t,
|
|
39
|
-
r: ca.r + (cb.r - ca.r) * t,
|
|
40
|
-
})
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/** Muted foreground — half-way between background and ink. */
|
|
44
|
-
export function muted(p: AimuxPalette): string {
|
|
45
|
-
return mix(p.neutral, p.ink, 0.55)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/** Slightly recessed foreground for line numbers / placeholders. */
|
|
49
|
-
export function faint(p: AimuxPalette): string {
|
|
50
|
-
return mix(p.neutral, p.ink, 0.3)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/** A surface tone above the base background — sidebars, headers. */
|
|
54
|
-
export function elevated(p: AimuxPalette): string {
|
|
55
|
-
return mix(p.neutral, p.ink, 0.04)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/** Hover/highlight surface (line highlight, list hover). */
|
|
59
|
-
export function hover(p: AimuxPalette): string {
|
|
60
|
-
return mix(p.neutral, p.ink, 0.08)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/** Selected/active row surface. Falls back to a primary-tinted shade. */
|
|
64
|
-
export function selected(p: AimuxPalette): string {
|
|
65
|
-
return p.interactive ?? mix(p.neutral, p.primary, 0.18)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/** Subtle border between panels. */
|
|
69
|
-
export function border(p: AimuxPalette): string {
|
|
70
|
-
return mix(p.neutral, p.ink, 0.18)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/** Background tint for inserted diff lines. */
|
|
74
|
-
export function diffAddBg(p: AimuxPalette): string {
|
|
75
|
-
return p.diffAdd ?? mix(p.neutral, p.success, 0.18)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/** Background tint for removed diff lines. */
|
|
79
|
-
export function diffDeleteBg(p: AimuxPalette): string {
|
|
80
|
-
return p.diffDelete ?? mix(p.neutral, p.error, 0.18)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/** Resolve `accent`, falling back to `primary`. */
|
|
84
|
-
export function accent(p: AimuxPalette): string {
|
|
85
|
-
return p.accent ?? p.primary
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/** Merge a partial palette onto a base palette. */
|
|
89
|
-
export function extendPalette(
|
|
90
|
-
base: AimuxPalette,
|
|
91
|
-
overrides: Partial<AimuxPalette> | undefined
|
|
92
|
-
): AimuxPalette {
|
|
93
|
-
if (!overrides) return base
|
|
94
|
-
return { ...base, ...overrides }
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Resolved surface colors derived from the OKLCH neutral scale. Prefer this
|
|
99
|
-
* over the standalone `muted`/`faint`/`elevated`/… helpers for runtime UI —
|
|
100
|
-
* those still exist for syntax-theme generation and callers that can't
|
|
101
|
-
* provide a mode.
|
|
102
|
-
*/
|
|
103
|
-
export interface ResolvedSurfaces {
|
|
104
|
-
bg: string
|
|
105
|
-
border: string
|
|
106
|
-
elevated: string
|
|
107
|
-
faint: string
|
|
108
|
-
hover: string
|
|
109
|
-
muted: string
|
|
110
|
-
selected: string
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/** Compute surface tokens for a palette in a given mode. */
|
|
114
|
-
export function computeSurfaces(palette: AimuxPalette, mode: ThemeMode): ResolvedSurfaces {
|
|
115
|
-
const isDark = mode === 'dark'
|
|
116
|
-
const neutral = generateNeutralScale(palette.neutral, isDark, palette.ink)
|
|
117
|
-
const alpha = generateNeutralAlphaScale(neutral, isDark)
|
|
118
|
-
// `selected` is a subtle primary-tinted surface, not the raw `palette.interactive`
|
|
119
|
-
// seed. In opencode themes `interactive` seeds an OKLCH scale we don't port;
|
|
120
|
-
// using it raw produces eye-bleeding accents (e.g. carbonfox `#0f62fe`).
|
|
121
|
-
return {
|
|
122
|
-
bg: neutral[0],
|
|
123
|
-
border: alpha[6],
|
|
124
|
-
elevated: alpha[1],
|
|
125
|
-
faint: neutral[7],
|
|
126
|
-
hover: alpha[2],
|
|
127
|
-
muted: neutral[8],
|
|
128
|
-
selected: blend(palette.primary, neutral[0], 0.18),
|
|
129
|
-
}
|
|
130
|
-
}
|