@opencode/theme 2.0.14 → 2.0.15
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/index.d.ts +3 -3
- package/dist/tui/index.js +3 -3
- package/dist/tui/resolve.d.ts +2115 -0
- package/dist/tui/resolve.js +35 -11
- package/dist/tui/schema.d.ts +62 -147
- package/dist/tui/schema.js +14 -18
- package/dist/tui/types.d.ts +3 -3
- package/dist/tui/v1-migrate.js +12 -5
- package/package.json +1 -1
- package/dist/tui/categorical.d.ts +0 -1
- package/dist/tui/categorical.js +0 -1
package/dist/tui/resolve.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { RGBA } from "@opentui/core";
|
|
2
2
|
import { Schema } from "effect";
|
|
3
3
|
import { expandTheme, mergeTheme } from "./expand.js";
|
|
4
|
-
import { ActionState, ActionVariant,
|
|
5
|
-
import { selectThemeMode } from "./select.js";
|
|
4
|
+
import { ActionState, ActionVariant, HueStep, SurfaceName, ThemeDefinition, ThemeDocument, } from "./schema.js";
|
|
5
|
+
import { selectThemeMode, themeModes } from "./select.js";
|
|
6
6
|
const decodeThemeDefinitionSchema = Schema.decodeUnknownSync(ThemeDefinition, { reportInput: true });
|
|
7
|
+
const decodeThemeDocumentSchema = Schema.decodeUnknownSync(ThemeDocument, { reportInput: true });
|
|
7
8
|
function decodeThemeDefinition(input) {
|
|
8
9
|
try {
|
|
9
10
|
return decodeThemeDefinitionSchema(input);
|
|
@@ -17,6 +18,16 @@ export function themeDecodeError(error, name) {
|
|
|
17
18
|
const value = /got ("[^"]*"|\S+)/.exec(message)?.[1] ?? "value";
|
|
18
19
|
return new Error(`Invalid theme: ${name} ${value} is an invalid value`, { cause: error });
|
|
19
20
|
}
|
|
21
|
+
export function parseThemeDocument(input, name = "theme") {
|
|
22
|
+
try {
|
|
23
|
+
const document = decodeThemeDocumentSchema(input);
|
|
24
|
+
themeModes(document).forEach((mode) => resolveThemeDocument(document, mode));
|
|
25
|
+
return document;
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
throw themeDecodeError(error, name);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
20
31
|
export function resolveThemeDocument(document, mode) {
|
|
21
32
|
const selected = selectThemeMode(document, mode);
|
|
22
33
|
const definition = expandTheme(selected.theme);
|
|
@@ -27,7 +38,12 @@ export function resolveTheme(definition) {
|
|
|
27
38
|
}
|
|
28
39
|
function resolveExpandedTheme(definition) {
|
|
29
40
|
const hue = resolveHue(definition.hue);
|
|
30
|
-
const categorical = definition.categorical.map((name) =>
|
|
41
|
+
const categorical = definition.categorical.map((name) => {
|
|
42
|
+
const scale = hue[name];
|
|
43
|
+
if (!scale)
|
|
44
|
+
throw new Error(`Categorical hue "${name}" was not found`);
|
|
45
|
+
return scale;
|
|
46
|
+
});
|
|
31
47
|
const hueSteps = compileHueSteps(hue);
|
|
32
48
|
const base = tokens(definition);
|
|
33
49
|
const views = {};
|
|
@@ -132,11 +148,6 @@ function compileHueSteps(hue) {
|
|
|
132
148
|
function resolveHue(definition) {
|
|
133
149
|
const source = definition;
|
|
134
150
|
const cache = new Map();
|
|
135
|
-
const expected = new Set([...BaseHue.literals, ...HueAlias.literals]);
|
|
136
|
-
for (const name of Object.keys(source)) {
|
|
137
|
-
if (!expected.has(name))
|
|
138
|
-
throw new Error(`Unknown hue "${name}"`);
|
|
139
|
-
}
|
|
140
151
|
function resolve(name, stack) {
|
|
141
152
|
const hit = cache.get(name);
|
|
142
153
|
if (hit)
|
|
@@ -145,9 +156,11 @@ function resolveHue(definition) {
|
|
|
145
156
|
throw new Error(`Circular hue reference: ${[...stack, name].join(" -> ")}`);
|
|
146
157
|
const value = source[name];
|
|
147
158
|
if (typeof value === "string") {
|
|
148
|
-
const match = /^\$hue\.(
|
|
159
|
+
const match = /^\$hue\.(.+)$/.exec(value);
|
|
149
160
|
if (!match?.[1])
|
|
150
161
|
throw new Error(`Hue alias "${value}" must reference a hue scale`);
|
|
162
|
+
if (source[match[1]] === undefined)
|
|
163
|
+
throw new Error(`Hue alias "${value}" references a missing hue`);
|
|
151
164
|
const target = resolve(match[1], [...stack, name]);
|
|
152
165
|
const result = Object.fromEntries(HueStep.literals.map((step) => [step, RGBA.clone(target[step])]));
|
|
153
166
|
cache.set(name, result);
|
|
@@ -168,7 +181,7 @@ function resolveHue(definition) {
|
|
|
168
181
|
cache.set(name, result);
|
|
169
182
|
return result;
|
|
170
183
|
}
|
|
171
|
-
return Object.fromEntries(
|
|
184
|
+
return Object.fromEntries(Object.keys(source).map((name) => [name, resolve(name, [])]));
|
|
172
185
|
}
|
|
173
186
|
function createResolver(source) {
|
|
174
187
|
const cache = new Map();
|
|
@@ -196,7 +209,7 @@ function createResolver(source) {
|
|
|
196
209
|
return hit;
|
|
197
210
|
if (stack.includes(target))
|
|
198
211
|
throw new Error(`Circular theme reference: ${[...stack, target].join(" -> ")}`);
|
|
199
|
-
const result = resolve(
|
|
212
|
+
const result = resolve(readColor(source, target), target, [...stack, target]);
|
|
200
213
|
if (!(result instanceof RGBA))
|
|
201
214
|
throw new Error(`Theme reference "${value}" at "${path}" is not a color`);
|
|
202
215
|
cache.set(target, result);
|
|
@@ -204,6 +217,17 @@ function createResolver(source) {
|
|
|
204
217
|
}
|
|
205
218
|
return (value, path) => resolve(value, path);
|
|
206
219
|
}
|
|
220
|
+
function readColor(source, path) {
|
|
221
|
+
const match = /^hue\.(.+)\.(100|200|300|400|500|600|700|800|900)$/.exec(path);
|
|
222
|
+
if (!match?.[1] || !match[2])
|
|
223
|
+
return read(source, path);
|
|
224
|
+
const scales = source.hue;
|
|
225
|
+
const scale = isRecord(scales) ? scales[match[1]] : undefined;
|
|
226
|
+
const color = isRecord(scale) ? scale[match[2]] : undefined;
|
|
227
|
+
if (color === undefined)
|
|
228
|
+
throw new Error(`Theme reference "$${path}" was not found`);
|
|
229
|
+
return color;
|
|
230
|
+
}
|
|
207
231
|
function resolvedKey(key) {
|
|
208
232
|
if (!key.startsWith("$"))
|
|
209
233
|
return key;
|