@opencode/theme 2.0.8 → 2.0.10
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/dist/tui/categorical.d.ts +1 -0
- package/dist/tui/categorical.js +1 -0
- package/dist/tui/expand.js +8 -10
- package/dist/tui/index.d.ts +3 -3
- package/dist/tui/index.js +2 -2
- package/dist/tui/resolve.d.ts +2 -2
- package/dist/tui/resolve.js +49 -43
- package/dist/tui/schema.d.ts +1060 -4487
- package/dist/tui/schema.js +86 -49
- package/dist/tui/select.d.ts +3 -8
- package/dist/tui/select.js +2 -20
- package/dist/tui/syntax.d.ts +2 -2
- package/dist/tui/syntax.js +19 -19
- package/dist/tui/types.d.ts +16 -19
- package/dist/tui/v1-migrate.js +80 -55
- package/package.json +1 -1
- package/dist/tui/defaults.d.ts +0 -580
- package/dist/tui/defaults.js +0 -455
- package/dist/tui/fallback.d.ts +0 -2
- package/dist/tui/fallback.js +0 -56
package/dist/tui/v1-migrate.js
CHANGED
|
@@ -1,11 +1,36 @@
|
|
|
1
1
|
import { RGBA } from "@opentui/core";
|
|
2
2
|
import { oklchToHex, rgbToOklch } from "./color.js";
|
|
3
|
-
import { DEFAULT_CATEGORICAL
|
|
3
|
+
import { DEFAULT_CATEGORICAL } from "./categorical.js";
|
|
4
4
|
import { HueStep } from "./schema.js";
|
|
5
5
|
const chromaticHues = ["red", "orange", "yellow", "green", "cyan", "blue", "purple"];
|
|
6
6
|
const categoricalTokens = ["secondary", "accent", "success", "warning", "primary", "error"];
|
|
7
7
|
const minimumChroma = 0.03;
|
|
8
8
|
const lightThreshold = 0.6;
|
|
9
|
+
// Canonical swatches copied from the original default-theme classifier keep V1 migration self-contained.
|
|
10
|
+
const hueReferences = {
|
|
11
|
+
light: {
|
|
12
|
+
red: "#fca5a5",
|
|
13
|
+
orange: "#fdba74",
|
|
14
|
+
yellow: "#fde047",
|
|
15
|
+
green: "#86efac",
|
|
16
|
+
cyan: "#67e8f9",
|
|
17
|
+
blue: "#93c5fd",
|
|
18
|
+
purple: "#d8b4fe",
|
|
19
|
+
},
|
|
20
|
+
dark: {
|
|
21
|
+
red: "#b91c1c",
|
|
22
|
+
orange: "#c2410c",
|
|
23
|
+
yellow: "#a16207",
|
|
24
|
+
green: "#15803d",
|
|
25
|
+
cyan: "#0e7490",
|
|
26
|
+
blue: "#1d4ed8",
|
|
27
|
+
purple: "#7e22ce",
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
const hueAngles = Object.fromEntries(Object.entries(hueReferences).map(([level, colors]) => [
|
|
31
|
+
level,
|
|
32
|
+
Object.fromEntries(Object.entries(colors).map(([name, color]) => [name, toOklch(RGBA.fromHex(color)).h])),
|
|
33
|
+
]));
|
|
9
34
|
export function migrateV1(theme) {
|
|
10
35
|
const light = resolveV1(theme, "light");
|
|
11
36
|
const dark = resolveV1(theme, "dark");
|
|
@@ -13,18 +38,24 @@ export function migrateV1(theme) {
|
|
|
13
38
|
const lightMode = detectMode(light);
|
|
14
39
|
const darkMode = detectMode(dark);
|
|
15
40
|
if (lightMode === darkMode) {
|
|
41
|
+
const definition = migrateMode(lightMode === "light" ? light : dark, lightMode);
|
|
16
42
|
if (lightMode === "light")
|
|
17
|
-
return {
|
|
18
|
-
return {
|
|
43
|
+
return { base: base(definition), light: { hue: definition.hue } };
|
|
44
|
+
return { base: base(definition), dark: { hue: definition.hue } };
|
|
19
45
|
}
|
|
20
46
|
}
|
|
47
|
+
const lightDefinition = migrateMode(light, "light");
|
|
48
|
+
const darkDefinition = migrateMode(dark, "dark");
|
|
21
49
|
return {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
dark: migrateMode(dark, "dark"),
|
|
50
|
+
base: base(lightDefinition),
|
|
51
|
+
light: { hue: lightDefinition.hue },
|
|
52
|
+
dark: darkDefinition,
|
|
26
53
|
};
|
|
27
54
|
}
|
|
55
|
+
function base(definition) {
|
|
56
|
+
const { hue: _, ...base } = definition;
|
|
57
|
+
return base;
|
|
58
|
+
}
|
|
28
59
|
function detectMode(theme) {
|
|
29
60
|
return luminance(theme.text) > luminance(theme.background) ? "dark" : "light";
|
|
30
61
|
}
|
|
@@ -35,22 +66,22 @@ function migrateMode(theme, mode) {
|
|
|
35
66
|
const color = (key) => hex(theme[key]);
|
|
36
67
|
const selected = hex(selectedForeground(theme, theme.primary));
|
|
37
68
|
const destructive = hex(selectedForeground(theme, theme.error));
|
|
38
|
-
const hues = inferHues(theme
|
|
69
|
+
const hues = inferHues(theme);
|
|
39
70
|
const categorical = categoricalTokens.flatMap((token) => {
|
|
40
71
|
const hue = hues.byToken[token];
|
|
41
72
|
return hue ? [hue] : [];
|
|
42
73
|
});
|
|
43
74
|
const uniqueCategorical = categorical.filter((hue, index) => categorical.indexOf(hue) === index);
|
|
44
|
-
const text =
|
|
45
|
-
const textMuted =
|
|
46
|
-
const primary =
|
|
47
|
-
const background =
|
|
48
|
-
const backgroundPanel =
|
|
49
|
-
const backgroundMenu =
|
|
75
|
+
const text = "$hue.neutral.200";
|
|
76
|
+
const textMuted = "$hue.neutral.400";
|
|
77
|
+
const primary = "$hue.interactive.200";
|
|
78
|
+
const background = "$hue.neutral.800";
|
|
79
|
+
const backgroundPanel = "$hue.neutral.700";
|
|
80
|
+
const backgroundMenu = "$hue.neutral.600";
|
|
50
81
|
const backgroundRaisedMax = "$hue.neutral.500";
|
|
51
82
|
return referenceHues({
|
|
52
83
|
hue: {
|
|
53
|
-
gray: neutralScale(theme
|
|
84
|
+
gray: neutralScale(theme),
|
|
54
85
|
...Object.fromEntries(chromaticHues.map((name) => {
|
|
55
86
|
const match = hues.byHue[name];
|
|
56
87
|
return [name, match ? hueScale(match.color, mode) : "$hue.gray"];
|
|
@@ -61,20 +92,20 @@ function migrateMode(theme, mode) {
|
|
|
61
92
|
},
|
|
62
93
|
categorical: uniqueCategorical.length ? uniqueCategorical : DEFAULT_CATEGORICAL,
|
|
63
94
|
text: {
|
|
64
|
-
|
|
65
|
-
|
|
95
|
+
base: text,
|
|
96
|
+
muted: textMuted,
|
|
66
97
|
action: {
|
|
67
98
|
primary: {
|
|
68
|
-
|
|
99
|
+
base: "$text.base",
|
|
69
100
|
$disabled: textMuted,
|
|
70
101
|
$focused: selected,
|
|
71
102
|
$selected: primary,
|
|
72
103
|
},
|
|
73
|
-
secondary: {
|
|
74
|
-
destructive: {
|
|
104
|
+
secondary: { base: "$text.muted", $hovered: "$text.base" },
|
|
105
|
+
destructive: { base: destructive, $disabled: textMuted },
|
|
75
106
|
},
|
|
76
107
|
formfield: {
|
|
77
|
-
|
|
108
|
+
base: text,
|
|
78
109
|
$hovered: primary,
|
|
79
110
|
$focused: primary,
|
|
80
111
|
$pressed: primary,
|
|
@@ -82,36 +113,36 @@ function migrateMode(theme, mode) {
|
|
|
82
113
|
$selected: primary,
|
|
83
114
|
},
|
|
84
115
|
feedback: {
|
|
85
|
-
error: {
|
|
86
|
-
warning: {
|
|
87
|
-
success: {
|
|
88
|
-
info: {
|
|
116
|
+
error: { base: color("error") },
|
|
117
|
+
warning: { base: color("warning") },
|
|
118
|
+
success: { base: color("success") },
|
|
119
|
+
info: { base: color("info") },
|
|
89
120
|
},
|
|
90
121
|
},
|
|
91
122
|
background: {
|
|
92
|
-
|
|
123
|
+
base: background,
|
|
93
124
|
raised: {
|
|
94
125
|
base: backgroundPanel,
|
|
95
126
|
high: backgroundMenu,
|
|
96
127
|
max: backgroundRaisedMax,
|
|
97
128
|
},
|
|
98
129
|
action: {
|
|
99
|
-
primary: {
|
|
100
|
-
secondary: {
|
|
101
|
-
destructive: {
|
|
130
|
+
primary: { base: "transparent", $hovered: backgroundPanel, $focused: primary, $selected: "transparent" },
|
|
131
|
+
secondary: { base: "transparent" },
|
|
132
|
+
destructive: { base: color("error") },
|
|
102
133
|
},
|
|
103
134
|
formfield: {
|
|
104
|
-
|
|
135
|
+
base: "$background.base",
|
|
105
136
|
},
|
|
106
137
|
feedback: {
|
|
107
|
-
error: {
|
|
108
|
-
warning: {
|
|
109
|
-
success: {
|
|
110
|
-
info: {
|
|
138
|
+
error: { base: "$background.base" },
|
|
139
|
+
warning: { base: "$background.base" },
|
|
140
|
+
success: { base: "$background.base" },
|
|
141
|
+
info: { base: "$background.base" },
|
|
111
142
|
},
|
|
112
143
|
},
|
|
113
|
-
border: {
|
|
114
|
-
scrollbar: {
|
|
144
|
+
border: { base: color("border") },
|
|
145
|
+
scrollbar: { base: color("borderActive") },
|
|
115
146
|
diff: {
|
|
116
147
|
text: {
|
|
117
148
|
added: color("diffAdded"),
|
|
@@ -160,13 +191,12 @@ function migrateMode(theme, mode) {
|
|
|
160
191
|
imageText: color("markdownImageText"),
|
|
161
192
|
codeBlock: color("markdownCodeBlock"),
|
|
162
193
|
},
|
|
163
|
-
"@
|
|
194
|
+
"@dialog": {
|
|
164
195
|
background: {
|
|
165
|
-
|
|
196
|
+
base: "$background.raised.base",
|
|
166
197
|
action: { primary: { $hovered: "$background.raised.high" } },
|
|
167
198
|
},
|
|
168
199
|
},
|
|
169
|
-
"@context:overlay": { background: { default: "$background.raised.high" } },
|
|
170
200
|
});
|
|
171
201
|
}
|
|
172
202
|
function referenceHues(theme) {
|
|
@@ -221,7 +251,7 @@ function referenceHues(theme) {
|
|
|
221
251
|
}
|
|
222
252
|
return Object.fromEntries(Object.entries(theme).map(([key, value]) => [key, key === "hue" || key === "categorical" ? value : replace(value)]));
|
|
223
253
|
}
|
|
224
|
-
function inferHues(theme
|
|
254
|
+
function inferHues(theme) {
|
|
225
255
|
const colors = [
|
|
226
256
|
["accent", theme.accent],
|
|
227
257
|
["success", theme.success],
|
|
@@ -232,7 +262,7 @@ function inferHues(theme, mode) {
|
|
|
232
262
|
["secondary", theme.secondary],
|
|
233
263
|
];
|
|
234
264
|
const inferred = colors.reduce((result, [token, color]) => {
|
|
235
|
-
const nearest = inferHue(color
|
|
265
|
+
const nearest = inferHue(color);
|
|
236
266
|
if (!nearest)
|
|
237
267
|
return result;
|
|
238
268
|
const current = result.byHue[nearest.name];
|
|
@@ -247,7 +277,7 @@ function inferHues(theme, mode) {
|
|
|
247
277
|
["accent", theme.accent],
|
|
248
278
|
["primary", theme.primary],
|
|
249
279
|
].reduce((result, [token, color]) => {
|
|
250
|
-
const nearest = inferHue(color
|
|
280
|
+
const nearest = inferHue(color);
|
|
251
281
|
if (!nearest)
|
|
252
282
|
return result;
|
|
253
283
|
return {
|
|
@@ -256,21 +286,18 @@ function inferHues(theme, mode) {
|
|
|
256
286
|
};
|
|
257
287
|
}, inferred);
|
|
258
288
|
}
|
|
259
|
-
function inferHue(color
|
|
289
|
+
function inferHue(color) {
|
|
260
290
|
const value = toOklch(color);
|
|
261
291
|
if (ambiguous(color, value.c))
|
|
262
292
|
return;
|
|
263
|
-
const
|
|
293
|
+
const reference = value.l >= lightThreshold ? hueAngles.light : hueAngles.dark;
|
|
264
294
|
return chromaticHues
|
|
265
295
|
.map((name) => ({
|
|
266
296
|
name,
|
|
267
|
-
distance: hueDistance(value.h,
|
|
297
|
+
distance: hueDistance(value.h, reference[name]),
|
|
268
298
|
}))
|
|
269
299
|
.sort((first, second) => first.distance - second.distance)[0];
|
|
270
300
|
}
|
|
271
|
-
function inferenceAnchor(lightness) {
|
|
272
|
-
return lightness >= lightThreshold ? 300 : 700;
|
|
273
|
-
}
|
|
274
301
|
function hueDistance(first, second) {
|
|
275
302
|
const difference = Math.abs(first - second);
|
|
276
303
|
return Math.min(difference, 360 - difference);
|
|
@@ -328,13 +355,13 @@ function selectedForeground(theme, background) {
|
|
|
328
355
|
}
|
|
329
356
|
function hueScale(color, mode) {
|
|
330
357
|
const value = toOklch(color);
|
|
331
|
-
const anchor =
|
|
358
|
+
const anchor = 200;
|
|
332
359
|
const endpoint = mode === "light" ? Math.max(0.97, value.l) : Math.min(0.18, value.l);
|
|
333
360
|
const alpha = color.toInts()[3];
|
|
334
361
|
return Object.fromEntries(HueStep.literals.map((step) => {
|
|
335
362
|
if (step === anchor)
|
|
336
363
|
return [step, hex(color)];
|
|
337
|
-
const progress =
|
|
364
|
+
const progress = (step - anchor) / (900 - anchor);
|
|
338
365
|
const generated = oklchToHex({
|
|
339
366
|
l: value.l + (endpoint - value.l) * progress,
|
|
340
367
|
c: value.c * (1 - progress * 0.5),
|
|
@@ -343,8 +370,8 @@ function hueScale(color, mode) {
|
|
|
343
370
|
return [step, alpha === 255 ? generated : `${generated}${byte(alpha)}`];
|
|
344
371
|
}));
|
|
345
372
|
}
|
|
346
|
-
function neutralScale(theme
|
|
347
|
-
const anchors = neutralAnchors(theme
|
|
373
|
+
function neutralScale(theme) {
|
|
374
|
+
const anchors = neutralAnchors(theme);
|
|
348
375
|
return Object.fromEntries(HueStep.literals.map((step) => {
|
|
349
376
|
const exact = anchors.find((anchor) => anchor.step === step);
|
|
350
377
|
if (exact)
|
|
@@ -359,7 +386,7 @@ function neutralScale(theme, mode) {
|
|
|
359
386
|
return [step, interpolate(lower.color, upper.color, (step - lower.step) / (upper.step - lower.step))];
|
|
360
387
|
}));
|
|
361
388
|
}
|
|
362
|
-
function neutralAnchors(theme
|
|
389
|
+
function neutralAnchors(theme) {
|
|
363
390
|
const light = [
|
|
364
391
|
{ step: 200, color: theme.background },
|
|
365
392
|
{ step: 300, color: theme.backgroundPanel },
|
|
@@ -367,8 +394,6 @@ function neutralAnchors(theme, mode) {
|
|
|
367
394
|
{ step: 600, color: theme.textMuted },
|
|
368
395
|
{ step: 800, color: theme.text },
|
|
369
396
|
];
|
|
370
|
-
if (mode === "light")
|
|
371
|
-
return light;
|
|
372
397
|
return light.toReversed().map((source) => ({ ...source, step: (1000 - source.step) }));
|
|
373
398
|
}
|
|
374
399
|
function interpolate(first, second, amount) {
|