@kitlangton/knobs 0.4.0-next.0 → 0.4.0-next.1
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/README.md +288 -43
- package/dist/dev/{chunk-stbcgz1y.js → chunk-1qzffbpa.js} +443 -451
- package/dist/dev/{chunk-7xgkerd2.js → chunk-3ygqgy1x.js} +23 -1
- package/dist/dev/{chunk-pmkvb9ep.js → chunk-8mabjeyk.js} +1920 -507
- package/dist/dev/{chunk-t68smqkc.js → chunk-ayb292zj.js} +13 -11
- package/dist/dev/index.js +10 -5
- package/dist/index.js +25 -1
- package/dist/panel.js +2900 -1320
- package/dist/react.js +294 -6
- package/dist/solid.js +292 -4
- package/dist/themes.js +1509 -7
- package/dist/types/core/adapter.d.ts +6 -2
- package/dist/types/core/appearance.d.ts +44 -0
- package/dist/types/core/glide.d.ts +7 -0
- package/dist/types/core/motion.d.ts +66 -0
- package/dist/types/core/root.d.ts +13 -0
- package/dist/types/core/store.d.ts +18 -5
- package/dist/types/core/theme.d.ts +10 -3
- package/dist/types/index.d.ts +2 -1
- package/dist/types/panel/gpu/color.d.ts +6 -0
- package/dist/types/panel/motion.d.ts +1 -1
- package/dist/types/panel/styles.d.ts +2 -3
- package/dist/types/themes/define.d.ts +104 -0
- package/dist/types/themes/index.d.ts +11 -0
- package/dist/types/themes/knobs.d.ts +5 -0
- package/dist/types/themes/void.d.ts +8 -0
- package/dist/types/tokens/color.d.ts +42 -0
- package/dist/types/tokens/css.d.ts +13 -0
- package/dist/types/tokens/evaluate.d.ts +8 -0
- package/dist/types/tokens/index.d.ts +4 -0
- package/dist/types/tokens/schema.d.ts +1100 -0
- package/dist/types/ui/bento-css.d.ts +1 -1
- package/dist/types/ui/compare-css.d.ts +1 -1
- package/dist/types/ui/index.d.ts +1 -1
- package/dist/types/ui/look.d.ts +18 -13
- package/dist/types/ui/overlay-css.d.ts +1 -1
- package/dist/types/ui/readout-css.d.ts +1 -1
- package/dist/types/ui/readout-model.d.ts +5 -1
- package/dist/types/ui/rgba.d.ts +11 -0
- package/dist/ui-react.js +2320 -676
- package/dist/ui-solid.js +2320 -676
- package/dist/ui.js +2552 -906
- package/package.json +1 -1
package/dist/themes.js
CHANGED
|
@@ -1,3 +1,1470 @@
|
|
|
1
|
+
// src/tokens/color.ts
|
|
2
|
+
var clamp01 = (x) => Math.min(1, Math.max(0, x));
|
|
3
|
+
var toLinear = (c) => c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
|
|
4
|
+
var toGamma = (c) => c <= 0.0031308 ? 12.92 * c : 1.055 * c ** (1 / 2.4) - 0.055;
|
|
5
|
+
function linearToOklch([r, g, b, a]) {
|
|
6
|
+
const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
|
|
7
|
+
const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
|
|
8
|
+
const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
|
|
9
|
+
const L = 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s;
|
|
10
|
+
const A = 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s;
|
|
11
|
+
const B = 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s;
|
|
12
|
+
const c = Math.hypot(A, B);
|
|
13
|
+
const h = c < 0.0000001 ? 0 : (Math.atan2(B, A) * 180 / Math.PI + 360) % 360;
|
|
14
|
+
return { l: L, c, h, alpha: a };
|
|
15
|
+
}
|
|
16
|
+
function oklchToLinear({ l: L, c, h, alpha = 1 }) {
|
|
17
|
+
const hr = h * Math.PI / 180;
|
|
18
|
+
const A = c * Math.cos(hr);
|
|
19
|
+
const B = c * Math.sin(hr);
|
|
20
|
+
const l = (L + 0.3963377774 * A + 0.2158037573 * B) ** 3;
|
|
21
|
+
const m = (L - 0.1055613458 * A - 0.0638541728 * B) ** 3;
|
|
22
|
+
const s = (L - 0.0894841775 * A - 1.291485548 * B) ** 3;
|
|
23
|
+
return [
|
|
24
|
+
4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
|
|
25
|
+
-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
|
|
26
|
+
-0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s,
|
|
27
|
+
alpha
|
|
28
|
+
];
|
|
29
|
+
}
|
|
30
|
+
var inGamut = ([r, g, b]) => [r, g, b].every((x) => x >= -0.00001 && x <= 1 + 0.00001);
|
|
31
|
+
function oklchToLinearInGamut(color) {
|
|
32
|
+
let rgb = oklchToLinear(color);
|
|
33
|
+
if (inGamut(rgb))
|
|
34
|
+
return clampRgba(rgb);
|
|
35
|
+
let lo = 0;
|
|
36
|
+
let hi = color.c;
|
|
37
|
+
for (let i = 0;i < 24; i++) {
|
|
38
|
+
const mid = (lo + hi) / 2;
|
|
39
|
+
rgb = oklchToLinear({ ...color, c: mid });
|
|
40
|
+
if (inGamut(rgb))
|
|
41
|
+
lo = mid;
|
|
42
|
+
else
|
|
43
|
+
hi = mid;
|
|
44
|
+
}
|
|
45
|
+
return clampRgba(oklchToLinear({ ...color, c: lo }));
|
|
46
|
+
}
|
|
47
|
+
var clampRgba = ([r, g, b, a]) => [clamp01(r), clamp01(g), clamp01(b), clamp01(a)];
|
|
48
|
+
function parseColor(input) {
|
|
49
|
+
const s = input.trim().toLowerCase();
|
|
50
|
+
if (s === "transparent")
|
|
51
|
+
return [0, 0, 0, 0];
|
|
52
|
+
if (s.startsWith("#")) {
|
|
53
|
+
let hex = s.slice(1);
|
|
54
|
+
if (hex.length === 3 || hex.length === 4)
|
|
55
|
+
hex = [...hex].map((ch) => ch + ch).join("");
|
|
56
|
+
if (!/^[0-9a-f]{6}([0-9a-f]{2})?$/.test(hex))
|
|
57
|
+
throw new Error(`Invalid colour: ${input}`);
|
|
58
|
+
const n = (i) => Number.parseInt(hex.slice(i, i + 2), 16) / 255;
|
|
59
|
+
return [toLinear(n(0)), toLinear(n(2)), toLinear(n(4)), hex.length === 8 ? n(6) : 1];
|
|
60
|
+
}
|
|
61
|
+
const fn = /^(oklch|rgba?)\(([^)]*)\)$/.exec(s);
|
|
62
|
+
if (!fn)
|
|
63
|
+
throw new Error(`Unsupported colour: ${input}`);
|
|
64
|
+
const parts = fn[2].split(/[\s,/]+/).filter(Boolean);
|
|
65
|
+
const num = (p, scale) => p === undefined ? 1 : p.endsWith("%") ? Number.parseFloat(p) / 100 : Number.parseFloat(p) / scale;
|
|
66
|
+
if (fn[1] === "oklch") {
|
|
67
|
+
const l = num(parts[0], 1);
|
|
68
|
+
return oklchToLinearInGamut({
|
|
69
|
+
l,
|
|
70
|
+
c: Number.parseFloat(parts[1]),
|
|
71
|
+
h: Number.parseFloat(parts[2]),
|
|
72
|
+
alpha: num(parts[3], 1)
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
return [
|
|
76
|
+
toLinear(num(parts[0], 255)),
|
|
77
|
+
toLinear(num(parts[1], 255)),
|
|
78
|
+
toLinear(num(parts[2], 255)),
|
|
79
|
+
num(parts[3], 1)
|
|
80
|
+
];
|
|
81
|
+
}
|
|
82
|
+
var toOklch = (input) => linearToOklch(parseColor(input));
|
|
83
|
+
var byte = (c) => Math.round(clamp01(c) * 255).toString(16).padStart(2, "0");
|
|
84
|
+
function formatHex([r, g, b, a]) {
|
|
85
|
+
const rgb = `#${byte(toGamma(r))}${byte(toGamma(g))}${byte(toGamma(b))}`;
|
|
86
|
+
return a >= 0.9995 ? rgb : rgb + byte(a);
|
|
87
|
+
}
|
|
88
|
+
var oklchToHex = (color) => formatHex(oklchToLinearInGamut(color));
|
|
89
|
+
var normalize = (input) => formatHex(parseColor(input));
|
|
90
|
+
function withAlpha(input, alpha) {
|
|
91
|
+
const [r, g, b, a] = parseColor(input);
|
|
92
|
+
return formatHex([r, g, b, a * alpha]);
|
|
93
|
+
}
|
|
94
|
+
function over(top, bottom) {
|
|
95
|
+
const t = parseColor(top);
|
|
96
|
+
const b = parseColor(bottom);
|
|
97
|
+
const a = t[3];
|
|
98
|
+
const mix = (i) => toLinear(toGamma(t[i]) * a + toGamma(b[i]) * (1 - a));
|
|
99
|
+
return formatHex([mix(0), mix(1), mix(2), 1]);
|
|
100
|
+
}
|
|
101
|
+
function apcaY(input) {
|
|
102
|
+
const [r, g, b] = parseColor(input).map(toGamma);
|
|
103
|
+
return 0.2126729 * r ** 2.4 + 0.7151522 * g ** 2.4 + 0.072175 * b ** 2.4;
|
|
104
|
+
}
|
|
105
|
+
function apca(text, background) {
|
|
106
|
+
const bgOpaque = parseColor(background)[3] < 1 ? over(background, "#000") : background;
|
|
107
|
+
const fg = parseColor(text)[3] < 1 ? over(text, bgOpaque) : text;
|
|
108
|
+
const soft = (y) => y > 0.022 ? y : y + (0.022 - y) ** 1.414;
|
|
109
|
+
const yt = soft(apcaY(fg));
|
|
110
|
+
const yb = soft(apcaY(bgOpaque));
|
|
111
|
+
if (Math.abs(yb - yt) < 0.0005)
|
|
112
|
+
return 0;
|
|
113
|
+
if (yb > yt) {
|
|
114
|
+
const sapc = (yb ** 0.56 - yt ** 0.57) * 1.14;
|
|
115
|
+
return sapc < 0.1 ? 0 : (sapc - 0.027) * 100;
|
|
116
|
+
}
|
|
117
|
+
const sapc = (yb ** 0.65 - yt ** 0.62) * 1.14;
|
|
118
|
+
return sapc > -0.1 ? 0 : -(sapc + 0.027) * 100;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// src/tokens/schema.ts
|
|
122
|
+
var theme = { from: "theme" };
|
|
123
|
+
var css = (s) => ({ css: s });
|
|
124
|
+
var value = (s) => ({ value: s });
|
|
125
|
+
var alpha = (pct, of = "var(--k-fg)") => `color-mix(in oklch,${of} calc(${pct}% * var(--k-contrast)),transparent)`;
|
|
126
|
+
var TOKENS = [
|
|
127
|
+
{
|
|
128
|
+
name: "accent",
|
|
129
|
+
tier: "input",
|
|
130
|
+
type: "color",
|
|
131
|
+
group: "Accent",
|
|
132
|
+
source: theme,
|
|
133
|
+
doc: "The one accent: primary actions, handles, focus. Hover, soft and selection derive from it in CSS.",
|
|
134
|
+
deprecated: ["--ku-accent"]
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: "contrast",
|
|
138
|
+
tier: "input",
|
|
139
|
+
type: "number",
|
|
140
|
+
group: "Inputs",
|
|
141
|
+
source: theme,
|
|
142
|
+
doc: "Contrast multiplier for fills and alpha borders (1 = default; the theme's 0–100 dial maps 50 → 1)."
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: "radius",
|
|
146
|
+
tier: "input",
|
|
147
|
+
type: "length",
|
|
148
|
+
group: "Shape",
|
|
149
|
+
source: theme,
|
|
150
|
+
doc: "Control corner radius. 0 squares everything, including capsules. Scales with density.",
|
|
151
|
+
deprecated: ["--ku-radius"],
|
|
152
|
+
resolve: "round(calc($ * (1 + (var(--_k-density) - 1) * 1.5)),2px)"
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
name: "density",
|
|
156
|
+
tier: "input",
|
|
157
|
+
type: "number",
|
|
158
|
+
group: "Size",
|
|
159
|
+
source: theme,
|
|
160
|
+
doc: "Size multiplier: compact .875, default 1, comfortable 1.1875."
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: "font",
|
|
164
|
+
tier: "input",
|
|
165
|
+
type: "font",
|
|
166
|
+
group: "Type",
|
|
167
|
+
source: theme,
|
|
168
|
+
doc: "UI font stack.",
|
|
169
|
+
deprecated: ["--ku-font"]
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
name: "mono",
|
|
173
|
+
tier: "input",
|
|
174
|
+
type: "font",
|
|
175
|
+
group: "Type",
|
|
176
|
+
source: theme,
|
|
177
|
+
doc: "Monospace font stack.",
|
|
178
|
+
deprecated: ["--ku-mono"]
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
name: "bg-page",
|
|
182
|
+
tier: "semantic",
|
|
183
|
+
type: "color",
|
|
184
|
+
group: "Surfaces",
|
|
185
|
+
source: theme,
|
|
186
|
+
doc: "The page behind panels; workspace backdrops.",
|
|
187
|
+
deprecated: ["--k-page", "--ku-page"]
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
name: "bg-inset",
|
|
191
|
+
tier: "semantic",
|
|
192
|
+
type: "color",
|
|
193
|
+
group: "Surfaces",
|
|
194
|
+
source: theme,
|
|
195
|
+
doc: "Wells sunk into a panel: tracks, inputs, segmented backgrounds."
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
name: "bg",
|
|
199
|
+
tier: "semantic",
|
|
200
|
+
type: "color",
|
|
201
|
+
group: "Surfaces",
|
|
202
|
+
source: theme,
|
|
203
|
+
doc: "The panel surface.",
|
|
204
|
+
deprecated: ["--ku-bg"]
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
name: "bg-raised",
|
|
208
|
+
tier: "semantic",
|
|
209
|
+
type: "color",
|
|
210
|
+
group: "Surfaces",
|
|
211
|
+
source: theme,
|
|
212
|
+
doc: "Raised within a panel: the active segment, cards on a panel."
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
name: "bg-overlay",
|
|
216
|
+
tier: "semantic",
|
|
217
|
+
type: "color",
|
|
218
|
+
group: "Surfaces",
|
|
219
|
+
source: theme,
|
|
220
|
+
doc: "Floating surfaces: menus, popovers, tooltips."
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
name: "fill",
|
|
224
|
+
tier: "semantic",
|
|
225
|
+
type: "color",
|
|
226
|
+
group: "Fills",
|
|
227
|
+
source: css(alpha(5.5)),
|
|
228
|
+
doc: "Resting fill for controls.",
|
|
229
|
+
deprecated: ["--k-surface", "--ku-surface"]
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
name: "fill-hover",
|
|
233
|
+
tier: "semantic",
|
|
234
|
+
type: "color",
|
|
235
|
+
group: "Fills",
|
|
236
|
+
source: css(alpha(8)),
|
|
237
|
+
doc: "Hovered fill."
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
name: "fill-selected",
|
|
241
|
+
tier: "semantic",
|
|
242
|
+
type: "color",
|
|
243
|
+
group: "Fills",
|
|
244
|
+
source: css(alpha(11)),
|
|
245
|
+
doc: "Pressed or selected fill.",
|
|
246
|
+
deprecated: ["--k-surface-hi", "--ku-surface-hi"]
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
name: "fg",
|
|
250
|
+
tier: "semantic",
|
|
251
|
+
type: "color",
|
|
252
|
+
group: "Foreground",
|
|
253
|
+
source: theme,
|
|
254
|
+
doc: "Primary text and icons (≥ Lc 90 on bg).",
|
|
255
|
+
deprecated: ["--k-text", "--ku-text"]
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
name: "fg-2",
|
|
259
|
+
tier: "semantic",
|
|
260
|
+
type: "color",
|
|
261
|
+
group: "Foreground",
|
|
262
|
+
source: theme,
|
|
263
|
+
doc: "Secondary text: labels (≥ Lc 75).",
|
|
264
|
+
deprecated: ["--k-label", "--ku-label"]
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
name: "fg-3",
|
|
268
|
+
tier: "semantic",
|
|
269
|
+
type: "color",
|
|
270
|
+
group: "Foreground",
|
|
271
|
+
source: theme,
|
|
272
|
+
doc: "Tertiary text: metadata, units, captions (≥ Lc 45).",
|
|
273
|
+
deprecated: ["--k-dim", "--ku-dim"]
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
name: "fg-4",
|
|
277
|
+
tier: "semantic",
|
|
278
|
+
type: "color",
|
|
279
|
+
group: "Foreground",
|
|
280
|
+
source: theme,
|
|
281
|
+
doc: "Placeholder and disabled text (≥ Lc 30)."
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
name: "border-subtle",
|
|
285
|
+
tier: "semantic",
|
|
286
|
+
type: "color",
|
|
287
|
+
group: "Borders",
|
|
288
|
+
source: css(alpha(6)),
|
|
289
|
+
doc: "Hairline edges and dividers (below Lc 15 by design).",
|
|
290
|
+
deprecated: ["--k-edge"]
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
name: "border",
|
|
294
|
+
tier: "semantic",
|
|
295
|
+
type: "color",
|
|
296
|
+
group: "Borders",
|
|
297
|
+
source: css(alpha(10)),
|
|
298
|
+
doc: "Default borders.",
|
|
299
|
+
deprecated: ["--k-line", "--ku-line"]
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
name: "border-strong",
|
|
303
|
+
tier: "semantic",
|
|
304
|
+
type: "color",
|
|
305
|
+
group: "Borders",
|
|
306
|
+
source: theme,
|
|
307
|
+
doc: "Interactive edges (≥ Lc 15; solid).",
|
|
308
|
+
deprecated: ["--k-line-hi", "--ku-line-hi"]
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
name: "accent-hover",
|
|
312
|
+
tier: "semantic",
|
|
313
|
+
type: "color",
|
|
314
|
+
group: "Accent",
|
|
315
|
+
source: css("color-mix(in oklch,var(--k-accent) 90%,var(--k-bg))"),
|
|
316
|
+
doc: "Hovered accent."
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
name: "accent-soft",
|
|
320
|
+
tier: "semantic",
|
|
321
|
+
type: "color",
|
|
322
|
+
group: "Accent",
|
|
323
|
+
source: css("color-mix(in oklch,var(--k-accent) 15%,transparent)"),
|
|
324
|
+
doc: "Accent tint behind accent content."
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
name: "accent-fg",
|
|
328
|
+
tier: "semantic",
|
|
329
|
+
type: "color",
|
|
330
|
+
group: "Accent",
|
|
331
|
+
source: theme,
|
|
332
|
+
doc: "Accent as text on bg (≥ Lc 60)."
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
name: "on-accent",
|
|
336
|
+
tier: "semantic",
|
|
337
|
+
type: "color",
|
|
338
|
+
group: "Accent",
|
|
339
|
+
source: theme,
|
|
340
|
+
doc: "Content placed on a solid accent."
|
|
341
|
+
},
|
|
342
|
+
{ name: "ok", tier: "semantic", type: "color", group: "Status", source: theme, doc: "Success." },
|
|
343
|
+
{
|
|
344
|
+
name: "warn",
|
|
345
|
+
tier: "semantic",
|
|
346
|
+
type: "color",
|
|
347
|
+
group: "Status",
|
|
348
|
+
source: theme,
|
|
349
|
+
doc: "Warning.",
|
|
350
|
+
deprecated: ["--ku-warn"]
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
name: "danger",
|
|
354
|
+
tier: "semantic",
|
|
355
|
+
type: "color",
|
|
356
|
+
group: "Status",
|
|
357
|
+
source: theme,
|
|
358
|
+
doc: "Error, destructive. Put text on danger-soft rather than bare bg.",
|
|
359
|
+
deprecated: ["--k-critical", "--ku-critical"]
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
name: "info",
|
|
363
|
+
tier: "semantic",
|
|
364
|
+
type: "color",
|
|
365
|
+
group: "Status",
|
|
366
|
+
source: theme,
|
|
367
|
+
doc: "Informational."
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
name: "ok-soft",
|
|
371
|
+
tier: "semantic",
|
|
372
|
+
type: "color",
|
|
373
|
+
group: "Status",
|
|
374
|
+
source: css("color-mix(in oklch,var(--k-ok) 15%,transparent)"),
|
|
375
|
+
doc: "Success tint."
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
name: "warn-soft",
|
|
379
|
+
tier: "semantic",
|
|
380
|
+
type: "color",
|
|
381
|
+
group: "Status",
|
|
382
|
+
source: css("color-mix(in oklch,var(--k-warn) 15%,transparent)"),
|
|
383
|
+
doc: "Warning tint."
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
name: "danger-soft",
|
|
387
|
+
tier: "semantic",
|
|
388
|
+
type: "color",
|
|
389
|
+
group: "Status",
|
|
390
|
+
source: css("color-mix(in oklch,var(--k-danger) 15%,transparent)"),
|
|
391
|
+
doc: "Danger tint."
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
name: "info-soft",
|
|
395
|
+
tier: "semantic",
|
|
396
|
+
type: "color",
|
|
397
|
+
group: "Status",
|
|
398
|
+
source: css("color-mix(in oklch,var(--k-info) 15%,transparent)"),
|
|
399
|
+
doc: "Info tint."
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
name: "focus",
|
|
403
|
+
tier: "semantic",
|
|
404
|
+
type: "color",
|
|
405
|
+
group: "Interaction",
|
|
406
|
+
source: css("var(--k-accent)"),
|
|
407
|
+
doc: "Focus ring colour (drawn as a 2px bg gap, then 2px of focus)."
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
name: "selection",
|
|
411
|
+
tier: "semantic",
|
|
412
|
+
type: "color",
|
|
413
|
+
group: "Interaction",
|
|
414
|
+
source: css("color-mix(in oklch,var(--k-accent) 24%,transparent)"),
|
|
415
|
+
doc: "Selected rows and ranges.",
|
|
416
|
+
deprecated: ["--k-ui-select", "--ku-select"]
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
name: "scrim",
|
|
420
|
+
tier: "semantic",
|
|
421
|
+
type: "color",
|
|
422
|
+
group: "Interaction",
|
|
423
|
+
source: theme,
|
|
424
|
+
doc: "Dimming behind modal layers."
|
|
425
|
+
},
|
|
426
|
+
{
|
|
427
|
+
name: "diff-add",
|
|
428
|
+
tier: "semantic",
|
|
429
|
+
type: "color",
|
|
430
|
+
group: "Data",
|
|
431
|
+
source: css("var(--k-ok)"),
|
|
432
|
+
doc: "Added lines; line and word tints derive privately (12% / 38%)."
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
name: "diff-del",
|
|
436
|
+
tier: "semantic",
|
|
437
|
+
type: "color",
|
|
438
|
+
group: "Data",
|
|
439
|
+
source: css("var(--k-danger)"),
|
|
440
|
+
doc: "Deleted lines."
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
name: "diff-mod",
|
|
444
|
+
tier: "semantic",
|
|
445
|
+
type: "color",
|
|
446
|
+
group: "Data",
|
|
447
|
+
source: css("var(--k-warn)"),
|
|
448
|
+
doc: "Modified lines."
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
name: "series-1",
|
|
452
|
+
tier: "semantic",
|
|
453
|
+
type: "color",
|
|
454
|
+
group: "Data",
|
|
455
|
+
source: theme,
|
|
456
|
+
doc: "Chart series 1."
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
name: "series-2",
|
|
460
|
+
tier: "semantic",
|
|
461
|
+
type: "color",
|
|
462
|
+
group: "Data",
|
|
463
|
+
source: theme,
|
|
464
|
+
doc: "Chart series 2."
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
name: "series-3",
|
|
468
|
+
tier: "semantic",
|
|
469
|
+
type: "color",
|
|
470
|
+
group: "Data",
|
|
471
|
+
source: theme,
|
|
472
|
+
doc: "Chart series 3."
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
name: "series-4",
|
|
476
|
+
tier: "semantic",
|
|
477
|
+
type: "color",
|
|
478
|
+
group: "Data",
|
|
479
|
+
source: theme,
|
|
480
|
+
doc: "Chart series 4."
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
name: "series-5",
|
|
484
|
+
tier: "semantic",
|
|
485
|
+
type: "color",
|
|
486
|
+
group: "Data",
|
|
487
|
+
source: theme,
|
|
488
|
+
doc: "Chart series 5."
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
name: "series-6",
|
|
492
|
+
tier: "semantic",
|
|
493
|
+
type: "color",
|
|
494
|
+
group: "Data",
|
|
495
|
+
source: theme,
|
|
496
|
+
doc: "Chart series 6."
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
name: "radius-panel",
|
|
500
|
+
tier: "semantic",
|
|
501
|
+
type: "length",
|
|
502
|
+
group: "Shape",
|
|
503
|
+
source: css("calc(var(--k-radius) + var(--k-unit))"),
|
|
504
|
+
doc: "Panel and card radius, concentric with controls.",
|
|
505
|
+
deprecated: ["--k-panel-radius", "--ku-panel-radius"]
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
name: "round",
|
|
509
|
+
tier: "semantic",
|
|
510
|
+
type: "length",
|
|
511
|
+
group: "Shape",
|
|
512
|
+
source: css("calc(var(--k-radius) * 999)"),
|
|
513
|
+
doc: "Capsule radius that squares when --k-radius is 0. Use instead of 999px."
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
name: "unit",
|
|
517
|
+
tier: "semantic",
|
|
518
|
+
type: "length",
|
|
519
|
+
group: "Size",
|
|
520
|
+
source: value("4px"),
|
|
521
|
+
doc: "The spacing unit."
|
|
522
|
+
},
|
|
523
|
+
{
|
|
524
|
+
name: "row",
|
|
525
|
+
tier: "semantic",
|
|
526
|
+
type: "length",
|
|
527
|
+
group: "Size",
|
|
528
|
+
source: css("round(calc(32px * var(--k-density)),2px)"),
|
|
529
|
+
doc: "Row height.",
|
|
530
|
+
deprecated: ["--ku-row"]
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
name: "width",
|
|
534
|
+
tier: "semantic",
|
|
535
|
+
type: "length",
|
|
536
|
+
group: "Size",
|
|
537
|
+
source: value("288px"),
|
|
538
|
+
doc: "Panel width."
|
|
539
|
+
},
|
|
540
|
+
{
|
|
541
|
+
name: "font-size",
|
|
542
|
+
tier: "semantic",
|
|
543
|
+
type: "length",
|
|
544
|
+
group: "Type",
|
|
545
|
+
source: css("round(calc(12px * (1 + (var(--k-density) - 1) * .5)),1px)"),
|
|
546
|
+
doc: "Body size; a 5-step scale derives privately.",
|
|
547
|
+
deprecated: ["--ku-font-size"]
|
|
548
|
+
},
|
|
549
|
+
{
|
|
550
|
+
name: "value-font",
|
|
551
|
+
tier: "semantic",
|
|
552
|
+
type: "font",
|
|
553
|
+
group: "Type",
|
|
554
|
+
source: css("var(--k-font)"),
|
|
555
|
+
doc: "Font for readouts and values (labPreset: mono).",
|
|
556
|
+
deprecated: ["--ku-value-font"]
|
|
557
|
+
},
|
|
558
|
+
{
|
|
559
|
+
name: "shadow-raised",
|
|
560
|
+
tier: "semantic",
|
|
561
|
+
type: "shadow",
|
|
562
|
+
group: "Material",
|
|
563
|
+
source: theme,
|
|
564
|
+
doc: "Small lift for raised controls.",
|
|
565
|
+
deprecated: ["--k-lift-shadow"]
|
|
566
|
+
},
|
|
567
|
+
{
|
|
568
|
+
name: "shadow-overlay",
|
|
569
|
+
tier: "semantic",
|
|
570
|
+
type: "shadow",
|
|
571
|
+
group: "Material",
|
|
572
|
+
source: theme,
|
|
573
|
+
doc: "Floating panels, menus, popovers.",
|
|
574
|
+
deprecated: ["--k-shadow", "--ku-shadow"]
|
|
575
|
+
},
|
|
576
|
+
{
|
|
577
|
+
name: "glass",
|
|
578
|
+
tier: "semantic",
|
|
579
|
+
type: "number",
|
|
580
|
+
group: "Material",
|
|
581
|
+
source: theme,
|
|
582
|
+
doc: "Backdrop glass amount (0 = opaque)."
|
|
583
|
+
},
|
|
584
|
+
{
|
|
585
|
+
name: "glow",
|
|
586
|
+
tier: "semantic",
|
|
587
|
+
type: "number",
|
|
588
|
+
group: "Material",
|
|
589
|
+
source: theme,
|
|
590
|
+
doc: "Specular glow amount."
|
|
591
|
+
},
|
|
592
|
+
{
|
|
593
|
+
name: "rim",
|
|
594
|
+
tier: "semantic",
|
|
595
|
+
type: "color",
|
|
596
|
+
group: "Material",
|
|
597
|
+
source: theme,
|
|
598
|
+
doc: "Top-edge highlight hairline.",
|
|
599
|
+
deprecated: ["--ku-rim"]
|
|
600
|
+
},
|
|
601
|
+
{
|
|
602
|
+
name: "spring",
|
|
603
|
+
tier: "semantic",
|
|
604
|
+
type: "spring",
|
|
605
|
+
group: "Motion",
|
|
606
|
+
source: value("0.3 0"),
|
|
607
|
+
doc: "Default spring as `duration bounce` (the motion module's `default`)."
|
|
608
|
+
},
|
|
609
|
+
{
|
|
610
|
+
name: "hover-in",
|
|
611
|
+
tier: "semantic",
|
|
612
|
+
type: "number",
|
|
613
|
+
group: "Motion",
|
|
614
|
+
source: value("0"),
|
|
615
|
+
doc: "Hover wash fade-in, unitless milliseconds.",
|
|
616
|
+
deprecated: ["--ku-hover-in"]
|
|
617
|
+
},
|
|
618
|
+
{
|
|
619
|
+
name: "hover-out",
|
|
620
|
+
tier: "semantic",
|
|
621
|
+
type: "number",
|
|
622
|
+
group: "Motion",
|
|
623
|
+
source: value("120"),
|
|
624
|
+
doc: "Hover wash fade-out, unitless milliseconds.",
|
|
625
|
+
deprecated: ["--ku-hover-out"]
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
name: "z",
|
|
629
|
+
tier: "semantic",
|
|
630
|
+
type: "integer",
|
|
631
|
+
group: "Motion",
|
|
632
|
+
source: value("2147480000"),
|
|
633
|
+
doc: "Base of knobs' stacking ladder; layers add small offsets."
|
|
634
|
+
},
|
|
635
|
+
{
|
|
636
|
+
name: "slider-track",
|
|
637
|
+
tier: "hook",
|
|
638
|
+
type: "color",
|
|
639
|
+
group: "Hooks",
|
|
640
|
+
source: css("var(--k-fill)"),
|
|
641
|
+
doc: "Slider track."
|
|
642
|
+
},
|
|
643
|
+
{
|
|
644
|
+
name: "slider-fill",
|
|
645
|
+
tier: "hook",
|
|
646
|
+
type: "color",
|
|
647
|
+
group: "Hooks",
|
|
648
|
+
source: css("color-mix(in oklch,var(--k-accent) 20%,var(--k-fill-selected))"),
|
|
649
|
+
doc: "Slider value fill.",
|
|
650
|
+
deprecated: ["--k-fill-rest"]
|
|
651
|
+
},
|
|
652
|
+
{
|
|
653
|
+
name: "slider-handle",
|
|
654
|
+
tier: "hook",
|
|
655
|
+
type: "color",
|
|
656
|
+
group: "Hooks",
|
|
657
|
+
source: css("var(--k-accent)"),
|
|
658
|
+
doc: "Slider handle and range thumbs.",
|
|
659
|
+
deprecated: ["--k-handle"]
|
|
660
|
+
},
|
|
661
|
+
{
|
|
662
|
+
name: "toggle-thumb-off",
|
|
663
|
+
tier: "hook",
|
|
664
|
+
type: "color",
|
|
665
|
+
group: "Hooks",
|
|
666
|
+
source: css("#ffffff"),
|
|
667
|
+
doc: "A switch's thumb while off, and the ring around colour and gradient thumbs.",
|
|
668
|
+
deprecated: ["--k-thumb"]
|
|
669
|
+
},
|
|
670
|
+
{
|
|
671
|
+
name: "toggle-track",
|
|
672
|
+
tier: "hook",
|
|
673
|
+
type: "color",
|
|
674
|
+
group: "Hooks",
|
|
675
|
+
source: css("var(--k-fill-selected)"),
|
|
676
|
+
doc: "Toggle track, off."
|
|
677
|
+
},
|
|
678
|
+
{
|
|
679
|
+
name: "toggle-track-on",
|
|
680
|
+
tier: "hook",
|
|
681
|
+
type: "color",
|
|
682
|
+
group: "Hooks",
|
|
683
|
+
source: css("var(--k-accent)"),
|
|
684
|
+
doc: "Toggle track, on."
|
|
685
|
+
},
|
|
686
|
+
{
|
|
687
|
+
name: "toggle-thumb",
|
|
688
|
+
tier: "hook",
|
|
689
|
+
type: "color",
|
|
690
|
+
group: "Hooks",
|
|
691
|
+
source: css("var(--k-on-accent)"),
|
|
692
|
+
doc: "Toggle thumb."
|
|
693
|
+
},
|
|
694
|
+
{
|
|
695
|
+
name: "segmented-track",
|
|
696
|
+
tier: "hook",
|
|
697
|
+
type: "color",
|
|
698
|
+
group: "Hooks",
|
|
699
|
+
source: css("var(--k-bg-inset)"),
|
|
700
|
+
doc: "Segmented control background.",
|
|
701
|
+
deprecated: ["--k-seg-bg", "--ku-seg-bg"]
|
|
702
|
+
},
|
|
703
|
+
{
|
|
704
|
+
name: "segmented-active",
|
|
705
|
+
tier: "hook",
|
|
706
|
+
type: "color",
|
|
707
|
+
group: "Hooks",
|
|
708
|
+
source: css("var(--k-bg-raised)"),
|
|
709
|
+
doc: "Active segment.",
|
|
710
|
+
deprecated: ["--k-seg-active"]
|
|
711
|
+
},
|
|
712
|
+
{
|
|
713
|
+
name: "timeline-playhead",
|
|
714
|
+
tier: "hook",
|
|
715
|
+
type: "color",
|
|
716
|
+
group: "Hooks",
|
|
717
|
+
source: css("var(--k-accent)"),
|
|
718
|
+
doc: "Timeline playhead."
|
|
719
|
+
},
|
|
720
|
+
{
|
|
721
|
+
name: "split-gutter",
|
|
722
|
+
tier: "hook",
|
|
723
|
+
type: "color",
|
|
724
|
+
group: "Hooks",
|
|
725
|
+
source: css("var(--k-border-subtle)"),
|
|
726
|
+
doc: "Split pane divider.",
|
|
727
|
+
deprecated: ["--k-ui-divider", "--ku-divider"]
|
|
728
|
+
},
|
|
729
|
+
{
|
|
730
|
+
name: "compare-divider",
|
|
731
|
+
tier: "hook",
|
|
732
|
+
type: "color",
|
|
733
|
+
group: "Hooks",
|
|
734
|
+
source: css("var(--k-fg)"),
|
|
735
|
+
doc: "Before/after divider line.",
|
|
736
|
+
deprecated: ["--k-compare-line"]
|
|
737
|
+
},
|
|
738
|
+
{
|
|
739
|
+
name: "compare-stage",
|
|
740
|
+
tier: "hook",
|
|
741
|
+
type: "color",
|
|
742
|
+
group: "Hooks",
|
|
743
|
+
source: css("var(--k-fill)"),
|
|
744
|
+
doc: "Compare stage background."
|
|
745
|
+
},
|
|
746
|
+
{
|
|
747
|
+
name: "activity-rail",
|
|
748
|
+
tier: "hook",
|
|
749
|
+
type: "color",
|
|
750
|
+
group: "Hooks",
|
|
751
|
+
source: css("var(--k-border-strong)"),
|
|
752
|
+
doc: "Activity rail line.",
|
|
753
|
+
deprecated: ["--k-activity-line"]
|
|
754
|
+
},
|
|
755
|
+
{
|
|
756
|
+
name: "picker-card",
|
|
757
|
+
tier: "hook",
|
|
758
|
+
type: "color",
|
|
759
|
+
group: "Hooks",
|
|
760
|
+
source: css("var(--k-fill)"),
|
|
761
|
+
doc: "Picker card."
|
|
762
|
+
},
|
|
763
|
+
{
|
|
764
|
+
name: "pane-bg",
|
|
765
|
+
tier: "hook",
|
|
766
|
+
type: "color",
|
|
767
|
+
group: "Hooks",
|
|
768
|
+
source: css("var(--k-bg)"),
|
|
769
|
+
doc: "knobs/ui pane card.",
|
|
770
|
+
deprecated: ["--k-ui-pane", "--ku-pane-bg"]
|
|
771
|
+
},
|
|
772
|
+
{
|
|
773
|
+
name: "button-bg",
|
|
774
|
+
tier: "hook",
|
|
775
|
+
type: "color",
|
|
776
|
+
group: "Hooks",
|
|
777
|
+
source: css("var(--k-fill)"),
|
|
778
|
+
doc: "Button fill."
|
|
779
|
+
},
|
|
780
|
+
{
|
|
781
|
+
name: "button-border",
|
|
782
|
+
tier: "hook",
|
|
783
|
+
type: "color",
|
|
784
|
+
group: "Hooks",
|
|
785
|
+
source: css("transparent"),
|
|
786
|
+
doc: "Button border.",
|
|
787
|
+
deprecated: ["--k-button-line"]
|
|
788
|
+
},
|
|
789
|
+
{
|
|
790
|
+
name: "button-fg",
|
|
791
|
+
tier: "hook",
|
|
792
|
+
type: "color",
|
|
793
|
+
group: "Hooks",
|
|
794
|
+
source: css("var(--k-fg)"),
|
|
795
|
+
doc: "Button text.",
|
|
796
|
+
deprecated: ["--k-button-color"]
|
|
797
|
+
},
|
|
798
|
+
{
|
|
799
|
+
name: "row-hover",
|
|
800
|
+
tier: "hook",
|
|
801
|
+
type: "color",
|
|
802
|
+
group: "Hooks",
|
|
803
|
+
source: css("color-mix(in oklch,var(--k-fill) 50%,transparent)"),
|
|
804
|
+
doc: "Row hover wash."
|
|
805
|
+
},
|
|
806
|
+
{
|
|
807
|
+
name: "group-label",
|
|
808
|
+
tier: "hook",
|
|
809
|
+
type: "color",
|
|
810
|
+
group: "Hooks",
|
|
811
|
+
source: css("var(--k-fg-3)"),
|
|
812
|
+
doc: "Folder and group headings.",
|
|
813
|
+
deprecated: ["--k-group-ink", "--k-group-color"]
|
|
814
|
+
},
|
|
815
|
+
{
|
|
816
|
+
name: "modified",
|
|
817
|
+
tier: "hook",
|
|
818
|
+
type: "color",
|
|
819
|
+
group: "Hooks",
|
|
820
|
+
source: css("var(--k-fg-3)"),
|
|
821
|
+
doc: "Marker for values changed from their default."
|
|
822
|
+
},
|
|
823
|
+
{
|
|
824
|
+
name: "tray-pad",
|
|
825
|
+
tier: "private",
|
|
826
|
+
type: "length",
|
|
827
|
+
group: "Private",
|
|
828
|
+
source: css("calc(var(--k-unit) * .5)"),
|
|
829
|
+
doc: "Padding inside a tray around its controls.",
|
|
830
|
+
deprecated: ["--k-tray-pad"]
|
|
831
|
+
},
|
|
832
|
+
{
|
|
833
|
+
name: "pad",
|
|
834
|
+
tier: "private",
|
|
835
|
+
type: "length",
|
|
836
|
+
group: "Private",
|
|
837
|
+
source: css("round(calc(10px * var(--k-density)),2px)"),
|
|
838
|
+
doc: "Panel padding.",
|
|
839
|
+
deprecated: ["--k-pad"]
|
|
840
|
+
},
|
|
841
|
+
{
|
|
842
|
+
name: "inset",
|
|
843
|
+
tier: "private",
|
|
844
|
+
type: "length",
|
|
845
|
+
group: "Private",
|
|
846
|
+
source: css("var(--_k-pad)"),
|
|
847
|
+
doc: "Row content inset.",
|
|
848
|
+
deprecated: ["--k-inset", "--ku-inset"]
|
|
849
|
+
},
|
|
850
|
+
{
|
|
851
|
+
name: "gap",
|
|
852
|
+
tier: "private",
|
|
853
|
+
type: "length",
|
|
854
|
+
group: "Private",
|
|
855
|
+
source: css("round(calc(var(--k-unit) * (1 + (var(--k-density) - 1) * 2.5)),1px)"),
|
|
856
|
+
doc: "Gap between rows.",
|
|
857
|
+
deprecated: ["--k-gap"]
|
|
858
|
+
},
|
|
859
|
+
{
|
|
860
|
+
name: "radius-md",
|
|
861
|
+
tier: "private",
|
|
862
|
+
type: "length",
|
|
863
|
+
group: "Private",
|
|
864
|
+
source: css("max(0px,calc(var(--k-radius) - var(--_k-tray-pad)))"),
|
|
865
|
+
doc: "Concentric radius one tray in.",
|
|
866
|
+
deprecated: ["--k-radius-md"]
|
|
867
|
+
},
|
|
868
|
+
{
|
|
869
|
+
name: "radius-sm",
|
|
870
|
+
tier: "private",
|
|
871
|
+
type: "length",
|
|
872
|
+
group: "Private",
|
|
873
|
+
source: css("max(0px,calc(var(--k-radius) - var(--_k-tray-pad) * 2))"),
|
|
874
|
+
doc: "Concentric radius two trays in.",
|
|
875
|
+
deprecated: ["--k-radius-sm"]
|
|
876
|
+
},
|
|
877
|
+
{
|
|
878
|
+
name: "control-h",
|
|
879
|
+
tier: "private",
|
|
880
|
+
type: "length",
|
|
881
|
+
group: "Private",
|
|
882
|
+
source: css("calc(var(--k-row) - var(--k-unit) * 2)"),
|
|
883
|
+
doc: "Control height inside a row.",
|
|
884
|
+
deprecated: ["--k-control-h", "--ku-control-h"]
|
|
885
|
+
},
|
|
886
|
+
{
|
|
887
|
+
name: "value-size",
|
|
888
|
+
tier: "private",
|
|
889
|
+
type: "length",
|
|
890
|
+
group: "Private",
|
|
891
|
+
source: css("calc(var(--k-font-size) - .5px)"),
|
|
892
|
+
doc: "Readout size.",
|
|
893
|
+
deprecated: ["--k-value-size", "--ku-value-size"]
|
|
894
|
+
},
|
|
895
|
+
{
|
|
896
|
+
name: "text-title",
|
|
897
|
+
tier: "private",
|
|
898
|
+
type: "length",
|
|
899
|
+
group: "Private",
|
|
900
|
+
source: css("calc(var(--k-font-size) + 1px)"),
|
|
901
|
+
doc: "Type scale: titles.",
|
|
902
|
+
deprecated: ["--k-text-title"]
|
|
903
|
+
},
|
|
904
|
+
{
|
|
905
|
+
name: "text-body",
|
|
906
|
+
tier: "private",
|
|
907
|
+
type: "length",
|
|
908
|
+
group: "Private",
|
|
909
|
+
source: css("var(--k-font-size)"),
|
|
910
|
+
doc: "Type scale: body.",
|
|
911
|
+
deprecated: ["--k-text-body"]
|
|
912
|
+
},
|
|
913
|
+
{
|
|
914
|
+
name: "text-control",
|
|
915
|
+
tier: "private",
|
|
916
|
+
type: "length",
|
|
917
|
+
group: "Private",
|
|
918
|
+
source: css("calc(var(--k-font-size) - .5px)"),
|
|
919
|
+
doc: "Type scale: controls.",
|
|
920
|
+
deprecated: ["--k-text-control"]
|
|
921
|
+
},
|
|
922
|
+
{
|
|
923
|
+
name: "text-meta",
|
|
924
|
+
tier: "private",
|
|
925
|
+
type: "length",
|
|
926
|
+
group: "Private",
|
|
927
|
+
source: css("calc(var(--k-font-size) - 1px)"),
|
|
928
|
+
doc: "Type scale: metadata.",
|
|
929
|
+
deprecated: ["--k-text-meta", "--ku-text-meta"]
|
|
930
|
+
},
|
|
931
|
+
{
|
|
932
|
+
name: "text-cap",
|
|
933
|
+
tier: "private",
|
|
934
|
+
type: "length",
|
|
935
|
+
group: "Private",
|
|
936
|
+
source: css("calc(var(--k-font-size) - 2px)"),
|
|
937
|
+
doc: "Type scale: caps and captions.",
|
|
938
|
+
deprecated: ["--k-text-cap"]
|
|
939
|
+
},
|
|
940
|
+
{
|
|
941
|
+
name: "weight",
|
|
942
|
+
tier: "private",
|
|
943
|
+
type: "number",
|
|
944
|
+
group: "Private",
|
|
945
|
+
source: value("400"),
|
|
946
|
+
doc: "Body weight.",
|
|
947
|
+
deprecated: ["--k-font-weight", "--ku-font-weight"]
|
|
948
|
+
},
|
|
949
|
+
{
|
|
950
|
+
name: "weight-label",
|
|
951
|
+
tier: "private",
|
|
952
|
+
type: "number",
|
|
953
|
+
group: "Private",
|
|
954
|
+
source: value("500"),
|
|
955
|
+
doc: "Label weight.",
|
|
956
|
+
deprecated: ["--k-label-weight", "--ku-label-weight"]
|
|
957
|
+
},
|
|
958
|
+
{
|
|
959
|
+
name: "weight-title",
|
|
960
|
+
tier: "private",
|
|
961
|
+
type: "number",
|
|
962
|
+
group: "Private",
|
|
963
|
+
source: value("600"),
|
|
964
|
+
doc: "Title weight.",
|
|
965
|
+
deprecated: ["--k-title-weight", "--ku-title-weight"]
|
|
966
|
+
},
|
|
967
|
+
{
|
|
968
|
+
name: "focus-ring",
|
|
969
|
+
tier: "private",
|
|
970
|
+
type: "shadow",
|
|
971
|
+
group: "Private",
|
|
972
|
+
source: css("0 0 0 2px var(--k-bg),0 0 0 4px var(--k-focus)"),
|
|
973
|
+
doc: "Two-layer focus ring: a bg gap, then the focus colour."
|
|
974
|
+
},
|
|
975
|
+
{
|
|
976
|
+
name: "diff-add-line",
|
|
977
|
+
tier: "private",
|
|
978
|
+
type: "color",
|
|
979
|
+
group: "Private",
|
|
980
|
+
source: css("color-mix(in oklch,var(--k-diff-add) 12%,transparent)"),
|
|
981
|
+
doc: "Added line tint."
|
|
982
|
+
},
|
|
983
|
+
{
|
|
984
|
+
name: "diff-add-word",
|
|
985
|
+
tier: "private",
|
|
986
|
+
type: "color",
|
|
987
|
+
group: "Private",
|
|
988
|
+
source: css("color-mix(in oklch,var(--k-diff-add) 38%,transparent)"),
|
|
989
|
+
doc: "Added word tint."
|
|
990
|
+
},
|
|
991
|
+
{
|
|
992
|
+
name: "diff-del-line",
|
|
993
|
+
tier: "private",
|
|
994
|
+
type: "color",
|
|
995
|
+
group: "Private",
|
|
996
|
+
source: css("color-mix(in oklch,var(--k-diff-del) 12%,transparent)"),
|
|
997
|
+
doc: "Deleted line tint."
|
|
998
|
+
},
|
|
999
|
+
{
|
|
1000
|
+
name: "diff-del-word",
|
|
1001
|
+
tier: "private",
|
|
1002
|
+
type: "color",
|
|
1003
|
+
group: "Private",
|
|
1004
|
+
source: css("color-mix(in oklch,var(--k-diff-del) 38%,transparent)"),
|
|
1005
|
+
doc: "Deleted word tint."
|
|
1006
|
+
},
|
|
1007
|
+
{
|
|
1008
|
+
name: "diff-mod-line",
|
|
1009
|
+
tier: "private",
|
|
1010
|
+
type: "color",
|
|
1011
|
+
group: "Private",
|
|
1012
|
+
source: css("color-mix(in oklch,var(--k-diff-mod) 12%,transparent)"),
|
|
1013
|
+
doc: "Modified line tint."
|
|
1014
|
+
},
|
|
1015
|
+
{
|
|
1016
|
+
name: "diff-mod-word",
|
|
1017
|
+
tier: "private",
|
|
1018
|
+
type: "color",
|
|
1019
|
+
group: "Private",
|
|
1020
|
+
source: css("color-mix(in oklch,var(--k-diff-mod) 38%,transparent)"),
|
|
1021
|
+
doc: "Modified word tint."
|
|
1022
|
+
}
|
|
1023
|
+
];
|
|
1024
|
+
var TOKEN_BY_NAME = new Map(TOKENS.map((t) => [t.name, t]));
|
|
1025
|
+
var cssName = (t) => `${t.tier === "private" ? "--_k-" : "--k-"}${t.name}`;
|
|
1026
|
+
var PROPERTY_TO_NAME = new Map(TOKENS.map((t) => [cssName(t), t.name]));
|
|
1027
|
+
var tokenForProperty = (property) => PROPERTY_TO_NAME.get(property);
|
|
1028
|
+
var DEPRECATED = new Map(TOKENS.flatMap((t) => (t.deprecated ?? []).map((old) => [old, cssName(t)])));
|
|
1029
|
+
|
|
1030
|
+
// src/tokens/css.ts
|
|
1031
|
+
function pair(def, dark, light) {
|
|
1032
|
+
if (dark === undefined && light === undefined)
|
|
1033
|
+
return;
|
|
1034
|
+
if (dark === undefined || light === undefined || dark === light || def.type !== "color")
|
|
1035
|
+
return dark ?? light;
|
|
1036
|
+
return `light-dark(${light},${dark})`;
|
|
1037
|
+
}
|
|
1038
|
+
function declaredValue(theme, def) {
|
|
1039
|
+
const name = def.name;
|
|
1040
|
+
const dark = theme.declared.dark[name];
|
|
1041
|
+
const light = theme.declared.light[name];
|
|
1042
|
+
if (def.type === "color" && dark === undefined !== (light === undefined))
|
|
1043
|
+
return pair(def, dark ?? theme.dark[name], light ?? theme.light[name]);
|
|
1044
|
+
return pair(def, dark, light);
|
|
1045
|
+
}
|
|
1046
|
+
var SCHEMES = [
|
|
1047
|
+
[":where(.knobs-root)", "light dark"],
|
|
1048
|
+
[
|
|
1049
|
+
':where(.dark,.dark-theme,[data-theme="dark"],[data-appearance="dark"],[data-knobs-theme="dark"]) :where(.knobs-root)',
|
|
1050
|
+
"dark"
|
|
1051
|
+
],
|
|
1052
|
+
[
|
|
1053
|
+
':where(.light,.light-theme,[data-theme="light"],[data-appearance="light"],[data-knobs-theme="light"]) :where(.knobs-root)',
|
|
1054
|
+
"light"
|
|
1055
|
+
],
|
|
1056
|
+
[":where(.knobs-root) :where(.knobs-root:not([data-appearance]))", "inherit"],
|
|
1057
|
+
[':where(.knobs-root[data-appearance="dark"])', "dark"],
|
|
1058
|
+
[':where(.knobs-root[data-appearance="light"])', "light"],
|
|
1059
|
+
[':where(.knobs-root[data-appearance="system"])', "light dark"],
|
|
1060
|
+
[':where(.knobs-root[data-appearance="inherit"])', "inherit"]
|
|
1061
|
+
];
|
|
1062
|
+
var APPEARANCE_CSS = SCHEMES.map(([selector, scheme]) => {
|
|
1063
|
+
const light = scheme === "light" ? "1" : scheme === "inherit" ? "inherit" : "0";
|
|
1064
|
+
const rule = `${selector}{color-scheme:${scheme};--_k-light:${light}}`;
|
|
1065
|
+
return scheme === "light dark" ? `${rule}
|
|
1066
|
+
@media(prefers-color-scheme:light){${selector}{--_k-light:1}}` : rule;
|
|
1067
|
+
}).join(`
|
|
1068
|
+
`);
|
|
1069
|
+
var privately = (css) => css.replace(/var\(--k-([a-z0-9-]+)/g, (m, name) => tokenForProperty(`--k-${name}`) ? `var(--_k-${name}` : m);
|
|
1070
|
+
function resolver(def) {
|
|
1071
|
+
const reads = [...def.deprecated ?? []];
|
|
1072
|
+
if (def.tier !== "private")
|
|
1073
|
+
reads.push(cssName(def));
|
|
1074
|
+
const source = def.source;
|
|
1075
|
+
const fallback = "css" in source ? privately(source.css) : ("value" in source) && def.tier === "private" ? source.value : undefined;
|
|
1076
|
+
let out = fallback ?? "";
|
|
1077
|
+
for (let i = reads.length - 1;i >= 0; i--)
|
|
1078
|
+
out = out === "" ? `var(${reads[i]})` : `var(${reads[i]},${out})`;
|
|
1079
|
+
return def.resolve ? privately(def.resolve).replaceAll("$", out) : out;
|
|
1080
|
+
}
|
|
1081
|
+
function tokensCss(theme) {
|
|
1082
|
+
const root = [];
|
|
1083
|
+
const resolved = [];
|
|
1084
|
+
for (const def of TOKENS) {
|
|
1085
|
+
const source = def.source;
|
|
1086
|
+
const own = declaredValue(theme, def) ?? ("from" in source ? "" : ("value" in source) && def.tier !== "private" ? source.value : undefined);
|
|
1087
|
+
if (own !== undefined && def.tier !== "private")
|
|
1088
|
+
root.push(`${cssName(def)}:${own}`);
|
|
1089
|
+
resolved.push(`--_k-${def.name}:${resolver(def)}`);
|
|
1090
|
+
}
|
|
1091
|
+
return `@layer knobs.tokens{
|
|
1092
|
+
:where(:root,:host){${root.join(";")}}
|
|
1093
|
+
:where(.knobs-root){${resolved.join(";")}}
|
|
1094
|
+
${APPEARANCE_CSS}
|
|
1095
|
+
}`;
|
|
1096
|
+
}
|
|
1097
|
+
function themeCss(theme, selector) {
|
|
1098
|
+
const decls = [];
|
|
1099
|
+
for (const def of TOKENS) {
|
|
1100
|
+
const own = declaredValue(theme, def);
|
|
1101
|
+
if (own !== undefined)
|
|
1102
|
+
decls.push(`${cssName(def)}:${own}`);
|
|
1103
|
+
}
|
|
1104
|
+
return `@layer knobs.tokens{${selector}{${decls.join(";")}}}`;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
// src/tokens/evaluate.ts
|
|
1108
|
+
function splitTop(s) {
|
|
1109
|
+
const out = [];
|
|
1110
|
+
let depth = 0;
|
|
1111
|
+
let start = 0;
|
|
1112
|
+
for (let i = 0;i < s.length; i++) {
|
|
1113
|
+
const ch = s[i];
|
|
1114
|
+
if (ch === "(")
|
|
1115
|
+
depth++;
|
|
1116
|
+
else if (ch === ")")
|
|
1117
|
+
depth--;
|
|
1118
|
+
else if (ch === "," && depth === 0) {
|
|
1119
|
+
out.push(s.slice(start, i).trim());
|
|
1120
|
+
start = i + 1;
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
out.push(s.slice(start).trim());
|
|
1124
|
+
return out;
|
|
1125
|
+
}
|
|
1126
|
+
var call = (s, fn) => s.startsWith(`${fn}(`) && s.endsWith(")") ? s.slice(fn.length + 1, -1) : undefined;
|
|
1127
|
+
function evaluate(input, lookup) {
|
|
1128
|
+
const s = input.trim();
|
|
1129
|
+
const v = call(s, "var");
|
|
1130
|
+
if (v !== undefined) {
|
|
1131
|
+
const [name, ...fallback] = splitTop(v);
|
|
1132
|
+
const value = lookup(name);
|
|
1133
|
+
if (value !== undefined)
|
|
1134
|
+
return evaluate(value, lookup);
|
|
1135
|
+
if (fallback.length)
|
|
1136
|
+
return evaluate(fallback.join(","), lookup);
|
|
1137
|
+
throw new Error(`Unresolved ${name}`);
|
|
1138
|
+
}
|
|
1139
|
+
const mix = call(s, "color-mix");
|
|
1140
|
+
if (mix !== undefined)
|
|
1141
|
+
return colorMix(mix, lookup);
|
|
1142
|
+
return normalize(s);
|
|
1143
|
+
}
|
|
1144
|
+
function percent(s, lookup) {
|
|
1145
|
+
const c = call(s, "calc");
|
|
1146
|
+
if (c === undefined)
|
|
1147
|
+
return Number.parseFloat(s) / 100;
|
|
1148
|
+
const [a, b] = c.split("*").map((x) => x.trim());
|
|
1149
|
+
const num = (x) => {
|
|
1150
|
+
const inner = call(x, "var");
|
|
1151
|
+
if (inner !== undefined)
|
|
1152
|
+
return Number.parseFloat(lookup(splitTop(inner)[0]) ?? Number.NaN.toString());
|
|
1153
|
+
return x.endsWith("%") ? Number.parseFloat(x) / 100 : Number.parseFloat(x);
|
|
1154
|
+
};
|
|
1155
|
+
const out = num(a) * num(b);
|
|
1156
|
+
if (!Number.isFinite(out))
|
|
1157
|
+
throw new Error(`Bad percentage: ${s}`);
|
|
1158
|
+
return out;
|
|
1159
|
+
}
|
|
1160
|
+
function stop(s, lookup) {
|
|
1161
|
+
const m = /^(.*?)\s+((?:calc\(.*\))|(?:[\d.]+%))$/.exec(s);
|
|
1162
|
+
if (!m)
|
|
1163
|
+
return { color: evaluate(s, lookup) };
|
|
1164
|
+
return { color: evaluate(m[1], lookup), p: percent(m[2], lookup) };
|
|
1165
|
+
}
|
|
1166
|
+
function colorMix(args, lookup) {
|
|
1167
|
+
const [space, a, b] = splitTop(args);
|
|
1168
|
+
if (space !== "in oklch")
|
|
1169
|
+
throw new Error(`Only color-mix(in oklch, …) is supported, got ${space}`);
|
|
1170
|
+
const x = stop(a, lookup);
|
|
1171
|
+
const y = stop(b, lookup);
|
|
1172
|
+
let p1 = x.p ?? (y.p === undefined ? 0.5 : 1 - y.p);
|
|
1173
|
+
let p2 = y.p ?? 1 - p1;
|
|
1174
|
+
const sum = p1 + p2;
|
|
1175
|
+
const scale = sum < 1 ? sum : 1;
|
|
1176
|
+
p1 /= sum;
|
|
1177
|
+
p2 /= sum;
|
|
1178
|
+
const ca = linearToOklch(parseColor(x.color));
|
|
1179
|
+
const cb = linearToOklch(parseColor(y.color));
|
|
1180
|
+
const a1 = ca.alpha ?? 1;
|
|
1181
|
+
const a2 = cb.alpha ?? 1;
|
|
1182
|
+
const alpha = a1 * p1 + a2 * p2;
|
|
1183
|
+
if (alpha <= 0)
|
|
1184
|
+
return "#00000000";
|
|
1185
|
+
const powerless = (c, alpha) => c.c < 0.0002 || alpha === 0;
|
|
1186
|
+
const h1 = powerless(ca, a1) ? cb.h : ca.h;
|
|
1187
|
+
const h2 = powerless(cb, a2) ? h1 : cb.h;
|
|
1188
|
+
let dh = h2 - h1;
|
|
1189
|
+
if (dh > 180)
|
|
1190
|
+
dh -= 360;
|
|
1191
|
+
if (dh < -180)
|
|
1192
|
+
dh += 360;
|
|
1193
|
+
const pre = (u, v) => (u * a1 * p1 + v * a2 * p2) / alpha;
|
|
1194
|
+
const rgb = oklchToLinear({
|
|
1195
|
+
l: pre(ca.l, cb.l),
|
|
1196
|
+
c: pre(ca.c, cb.c),
|
|
1197
|
+
h: (h1 + dh * p2 + 360) % 360
|
|
1198
|
+
});
|
|
1199
|
+
return formatHex([rgb[0], rgb[1], rgb[2], alpha * scale]);
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
// src/themes/define.ts
|
|
1203
|
+
var DEFAULT_SANS = 'system-ui,-apple-system,"SF Pro Text",sans-serif';
|
|
1204
|
+
var DEFAULT_MONO = '"SF Mono",SFMono-Regular,ui-monospace,Menlo,monospace';
|
|
1205
|
+
var BASE = {
|
|
1206
|
+
gray: { hue: 0, chroma: 0 },
|
|
1207
|
+
accent: "#ffffff",
|
|
1208
|
+
contrast: 50,
|
|
1209
|
+
radius: 8,
|
|
1210
|
+
density: "default",
|
|
1211
|
+
material: "solid",
|
|
1212
|
+
font: { sans: DEFAULT_SANS, mono: DEFAULT_MONO },
|
|
1213
|
+
tokens: { dark: {}, light: {} }
|
|
1214
|
+
};
|
|
1215
|
+
var DENSITY = { compact: 0.875, default: 1, comfortable: 1.1875 };
|
|
1216
|
+
var SURFACES = {
|
|
1217
|
+
dark: { "bg-page": 14.5, "bg-inset": 19.6, bg: 22.6, "bg-raised": 25.7, "bg-overlay": 28.1 },
|
|
1218
|
+
light: { "bg-page": 92.6, "bg-inset": 94.6, bg: 97.1, "bg-raised": 100, "bg-overlay": 100 }
|
|
1219
|
+
};
|
|
1220
|
+
var INKS = {
|
|
1221
|
+
dark: { fg: 99.7, "fg-2": 76.7, "fg-3": 48.4, "fg-4": 31.9, "border-strong": 15.8 },
|
|
1222
|
+
light: { fg: 98.35, "fg-2": 78, "fg-3": 50, "fg-4": 34, "border-strong": 17 }
|
|
1223
|
+
};
|
|
1224
|
+
var APCA_BUDGET = {
|
|
1225
|
+
fg: 90,
|
|
1226
|
+
"fg-2": 75,
|
|
1227
|
+
"fg-3": 45,
|
|
1228
|
+
"fg-4": 30,
|
|
1229
|
+
"accent-fg": 60,
|
|
1230
|
+
"border-strong": 15
|
|
1231
|
+
};
|
|
1232
|
+
var TINT = { surface: { dark: 0.5, light: 0.7 }, fg: 1.35, ink: 1.5, border: 1.25 };
|
|
1233
|
+
var STATUS = {
|
|
1234
|
+
dark: {
|
|
1235
|
+
ok: [78, 0.15, 155],
|
|
1236
|
+
warn: [83, 0.14, 80],
|
|
1237
|
+
danger: [70, 0.18, 25],
|
|
1238
|
+
info: [75, 0.13, 240]
|
|
1239
|
+
},
|
|
1240
|
+
light: {
|
|
1241
|
+
ok: [52, 0.14, 150],
|
|
1242
|
+
warn: [60, 0.14, 65],
|
|
1243
|
+
danger: [55, 0.2, 27],
|
|
1244
|
+
info: [53, 0.15, 245]
|
|
1245
|
+
}
|
|
1246
|
+
};
|
|
1247
|
+
var SERIES_HUES = [250, 155, 75, 25, 305, 195];
|
|
1248
|
+
var SERIES = { dark: { l: 74, c: 0.12 }, light: { l: 56, c: 0.14 } };
|
|
1249
|
+
var contrastMultiplier = (contrast) => 0.5 + Math.min(100, Math.max(0, contrast)) / 100;
|
|
1250
|
+
function fontStack(family, fallback) {
|
|
1251
|
+
if (family.includes(","))
|
|
1252
|
+
return family;
|
|
1253
|
+
const quoted = /\s/.test(family) && !/^["']/.test(family) ? `"${family}"` : family;
|
|
1254
|
+
return family === fallback ? family : `${quoted},${fallback}`;
|
|
1255
|
+
}
|
|
1256
|
+
function mergeInputs(parent, spec) {
|
|
1257
|
+
return {
|
|
1258
|
+
gray: { ...parent.gray, ...spec.gray },
|
|
1259
|
+
accent: spec.accent ?? parent.accent,
|
|
1260
|
+
contrast: spec.contrast ?? parent.contrast,
|
|
1261
|
+
radius: spec.radius ?? parent.radius,
|
|
1262
|
+
density: spec.density ?? parent.density,
|
|
1263
|
+
material: spec.material ?? parent.material,
|
|
1264
|
+
font: {
|
|
1265
|
+
sans: spec.font?.sans ? fontStack(spec.font.sans, DEFAULT_SANS) : parent.font.sans,
|
|
1266
|
+
mono: spec.font?.mono ? fontStack(spec.font.mono, DEFAULT_MONO) : parent.font.mono
|
|
1267
|
+
},
|
|
1268
|
+
tokens: {
|
|
1269
|
+
dark: { ...parent.tokens.dark, ...spec.tokens?.dark },
|
|
1270
|
+
light: { ...parent.tokens.light, ...spec.tokens?.light }
|
|
1271
|
+
}
|
|
1272
|
+
};
|
|
1273
|
+
}
|
|
1274
|
+
function meet(l, floor, bg, away, make) {
|
|
1275
|
+
let x = l;
|
|
1276
|
+
while (apca(make(x), bg) < floor + 0.5 && x >= 0 && x <= 100)
|
|
1277
|
+
x += away * 0.25;
|
|
1278
|
+
return make(Math.min(100, Math.max(0, x)));
|
|
1279
|
+
}
|
|
1280
|
+
function solve(target, bg, away, make) {
|
|
1281
|
+
let near = toOklch(bg).l * 100;
|
|
1282
|
+
let far = away > 0 ? 100 : 0;
|
|
1283
|
+
if (apca(make(far), bg) <= target)
|
|
1284
|
+
return far;
|
|
1285
|
+
for (let i = 0;i < 30; i++) {
|
|
1286
|
+
const mid = (near + far) / 2;
|
|
1287
|
+
if (apca(make(mid), bg) < target)
|
|
1288
|
+
near = mid;
|
|
1289
|
+
else
|
|
1290
|
+
far = mid;
|
|
1291
|
+
}
|
|
1292
|
+
return far;
|
|
1293
|
+
}
|
|
1294
|
+
function accentPair(inputs) {
|
|
1295
|
+
if (typeof inputs.accent !== "string")
|
|
1296
|
+
return { ...inputs.accent };
|
|
1297
|
+
const dark = inputs.accent;
|
|
1298
|
+
const o = toOklch(dark);
|
|
1299
|
+
const light = o.c < 0.02 ? oklchToHex({ l: 0.227, c: inputs.gray.chroma, h: inputs.gray.hue }) : oklchToHex({ l: Math.min(0.6, Math.max(0.45, o.l - 0.15)), c: o.c * 1.1, h: o.h });
|
|
1300
|
+
return { dark, light };
|
|
1301
|
+
}
|
|
1302
|
+
function generate(inputs, appearance, accent) {
|
|
1303
|
+
const m = contrastMultiplier(inputs.contrast);
|
|
1304
|
+
const { hue, chroma } = inputs.gray;
|
|
1305
|
+
const neutral = (l, tint) => oklchToHex({ l: l / 100, c: chroma * tint, h: hue });
|
|
1306
|
+
const user = inputs.tokens[appearance];
|
|
1307
|
+
const out = {};
|
|
1308
|
+
const surfaces = SURFACES[appearance];
|
|
1309
|
+
for (const [role, l] of Object.entries(surfaces)) {
|
|
1310
|
+
const spread = surfaces.bg + (l - surfaces.bg) * m;
|
|
1311
|
+
out[role] = user[role] ?? neutral(Math.min(100, Math.max(0, spread)), TINT.surface[appearance]);
|
|
1312
|
+
}
|
|
1313
|
+
const bg = out.bg;
|
|
1314
|
+
const away = appearance === "dark" ? 1 : -1;
|
|
1315
|
+
const inkSpread = 1 + (m - 1) * 0.4;
|
|
1316
|
+
for (const [role, target] of Object.entries(INKS[appearance])) {
|
|
1317
|
+
const tint = role === "fg" ? TINT.fg : role === "border-strong" ? TINT.border : TINT.ink;
|
|
1318
|
+
const make = (x) => neutral(x, tint);
|
|
1319
|
+
const l = solve(target * inkSpread, bg, away, make);
|
|
1320
|
+
out[role] = meet(l, APCA_BUDGET[role], bg, away, make);
|
|
1321
|
+
}
|
|
1322
|
+
out.accent = accent;
|
|
1323
|
+
const a = toOklch(accent);
|
|
1324
|
+
out["accent-fg"] = meet(a.l * 100, APCA_BUDGET["accent-fg"], bg, away, (x) => oklchToHex({ l: x / 100, c: a.c, h: a.h }));
|
|
1325
|
+
out["on-accent"] = apca("#111111", accent) >= apca("#ffffff", accent) ? "#111111" : "#ffffff";
|
|
1326
|
+
for (const [role, [l, c, h]] of Object.entries(STATUS[appearance]))
|
|
1327
|
+
out[role] = oklchToHex({ l: l / 100, c, h });
|
|
1328
|
+
const s = SERIES[appearance];
|
|
1329
|
+
const start = a.c >= 0.04 ? a.h - SERIES_HUES[0] : 0;
|
|
1330
|
+
SERIES_HUES.forEach((h, i) => {
|
|
1331
|
+
out[`series-${i + 1}`] = oklchToHex({ l: s.l / 100, c: s.c, h: (h + start + 360) % 360 });
|
|
1332
|
+
});
|
|
1333
|
+
out.scrim = appearance === "dark" ? "#00000099" : "#00000040";
|
|
1334
|
+
out.contrast = String(Math.round(m * 1000) / 1000);
|
|
1335
|
+
out.radius = `${inputs.radius}px`;
|
|
1336
|
+
out.density = String(DENSITY[inputs.density]);
|
|
1337
|
+
out.font = inputs.font.sans;
|
|
1338
|
+
out.mono = inputs.font.mono;
|
|
1339
|
+
const material = inputs.material;
|
|
1340
|
+
out.glass = material === "glass" ? "0.6" : "0";
|
|
1341
|
+
out.glow = material === "glass" ? "0.5" : "0";
|
|
1342
|
+
out.rim = material === "flat" ? "transparent" : appearance === "dark" ? "#ffffff1a" : "#ffffff99";
|
|
1343
|
+
if (material === "flat") {
|
|
1344
|
+
out["border-subtle"] = over(withAlpha(out.fg, 0.06 * m), bg);
|
|
1345
|
+
out.border = over(withAlpha(out.fg, 0.1 * m), bg);
|
|
1346
|
+
}
|
|
1347
|
+
return out;
|
|
1348
|
+
}
|
|
1349
|
+
function shadows(material, borderStrong) {
|
|
1350
|
+
if (material === "flat")
|
|
1351
|
+
return {
|
|
1352
|
+
"shadow-raised": "none",
|
|
1353
|
+
"shadow-overlay": `0 0 0 1px light-dark(${borderStrong.light},${borderStrong.dark})`
|
|
1354
|
+
};
|
|
1355
|
+
return {
|
|
1356
|
+
"shadow-raised": "0 1px 2px light-dark(#0000001f,#00000029)",
|
|
1357
|
+
"shadow-overlay": "0 12px 36px light-dark(#00000024,#00000085),0 1px 2px light-dark(#00000014,#0000004d)"
|
|
1358
|
+
};
|
|
1359
|
+
}
|
|
1360
|
+
function resolve(declared) {
|
|
1361
|
+
const raw = (name) => {
|
|
1362
|
+
const def = TOKEN_BY_NAME.get(name);
|
|
1363
|
+
const own = declared[name];
|
|
1364
|
+
if (own !== undefined)
|
|
1365
|
+
return own;
|
|
1366
|
+
const source = def.source;
|
|
1367
|
+
if ("css" in source)
|
|
1368
|
+
return source.css;
|
|
1369
|
+
if ("value" in source)
|
|
1370
|
+
return source.value;
|
|
1371
|
+
throw new Error(`Theme does not supply ${name}`);
|
|
1372
|
+
};
|
|
1373
|
+
const lookup = (property) => {
|
|
1374
|
+
const name = tokenForProperty(property);
|
|
1375
|
+
return name ? raw(name) : undefined;
|
|
1376
|
+
};
|
|
1377
|
+
const out = {};
|
|
1378
|
+
for (const t of TOKENS)
|
|
1379
|
+
out[t.name] = t.type === "color" ? evaluate(raw(t.name), lookup) : raw(t.name);
|
|
1380
|
+
return out;
|
|
1381
|
+
}
|
|
1382
|
+
function gpuOf(resolved) {
|
|
1383
|
+
const out = {};
|
|
1384
|
+
for (const t of TOKENS)
|
|
1385
|
+
if (t.type === "color")
|
|
1386
|
+
out[t.name] = parseColor(resolved[t.name]);
|
|
1387
|
+
return out;
|
|
1388
|
+
}
|
|
1389
|
+
function validate(name, inputs) {
|
|
1390
|
+
if (!/^[\w-]+$/.test(name))
|
|
1391
|
+
throw new Error(`Invalid theme name: ${name}`);
|
|
1392
|
+
if (name === "dark" || name === "light")
|
|
1393
|
+
throw new Error(`Reserved theme name: ${name}`);
|
|
1394
|
+
for (const appearance of ["dark", "light"])
|
|
1395
|
+
for (const key of Object.keys(inputs.tokens[appearance]))
|
|
1396
|
+
if (!TOKEN_BY_NAME.has(key))
|
|
1397
|
+
throw new Error(`Unknown token in theme ${name}: ${key}`);
|
|
1398
|
+
}
|
|
1399
|
+
function defineTheme(spec) {
|
|
1400
|
+
const inputs = mergeInputs(spec.extends?.inputs ?? BASE, spec);
|
|
1401
|
+
validate(spec.name, inputs);
|
|
1402
|
+
const accent = accentPair(inputs);
|
|
1403
|
+
const generated = {
|
|
1404
|
+
dark: generate(inputs, "dark", accent.dark),
|
|
1405
|
+
light: generate(inputs, "light", accent.light)
|
|
1406
|
+
};
|
|
1407
|
+
const material = shadows(inputs.material, {
|
|
1408
|
+
dark: inputs.tokens.dark["border-strong"] ?? generated.dark["border-strong"],
|
|
1409
|
+
light: inputs.tokens.light["border-strong"] ?? generated.light["border-strong"]
|
|
1410
|
+
});
|
|
1411
|
+
const declared = {
|
|
1412
|
+
dark: { ...generated.dark, ...material, ...inputs.tokens.dark },
|
|
1413
|
+
light: { ...generated.light, ...material, ...inputs.tokens.light }
|
|
1414
|
+
};
|
|
1415
|
+
for (const [key, dark] of Object.entries(declared.dark)) {
|
|
1416
|
+
const def = TOKEN_BY_NAME.get(key);
|
|
1417
|
+
const light = declared.light[key];
|
|
1418
|
+
if (def.type !== "color" && light !== undefined && light !== dark)
|
|
1419
|
+
throw new Error(`Theme ${spec.name}: only colours may differ by appearance (${key})`);
|
|
1420
|
+
}
|
|
1421
|
+
const dark = resolve(declared.dark);
|
|
1422
|
+
const light = resolve(declared.light);
|
|
1423
|
+
const theme = {
|
|
1424
|
+
name: spec.name,
|
|
1425
|
+
inputs,
|
|
1426
|
+
dark,
|
|
1427
|
+
light,
|
|
1428
|
+
declared,
|
|
1429
|
+
gpu: { dark: gpuOf(dark), light: gpuOf(light) },
|
|
1430
|
+
css: (options) => options?.selector ? themeCss(theme, options.selector) : tokensCss(theme)
|
|
1431
|
+
};
|
|
1432
|
+
return theme;
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
// src/themes/knobs.ts
|
|
1436
|
+
var knobs = defineTheme({
|
|
1437
|
+
name: "knobs",
|
|
1438
|
+
gray: { hue: 285, chroma: 0.004 },
|
|
1439
|
+
accent: { dark: "#ffffff", light: "#1c1c1e" },
|
|
1440
|
+
contrast: 50,
|
|
1441
|
+
radius: 8,
|
|
1442
|
+
density: "default",
|
|
1443
|
+
material: "glass"
|
|
1444
|
+
});
|
|
1445
|
+
|
|
1446
|
+
// src/themes/void.ts
|
|
1447
|
+
var voidTheme = defineTheme({
|
|
1448
|
+
name: "void",
|
|
1449
|
+
extends: knobs,
|
|
1450
|
+
gray: { hue: 0, chroma: 0 },
|
|
1451
|
+
accent: { dark: "#ffffff", light: "#1c1c1c" },
|
|
1452
|
+
material: "flat",
|
|
1453
|
+
tokens: {
|
|
1454
|
+
dark: {
|
|
1455
|
+
"bg-page": "#000000",
|
|
1456
|
+
"bg-inset": "#0a0a0a",
|
|
1457
|
+
bg: "#000000",
|
|
1458
|
+
"bg-raised": "#1c1c1e",
|
|
1459
|
+
"bg-overlay": "#2c2c2e",
|
|
1460
|
+
fg: "#ededed",
|
|
1461
|
+
"fg-2": "#cecece",
|
|
1462
|
+
"fg-3": "#989898",
|
|
1463
|
+
"fg-4": "#7a7a7a",
|
|
1464
|
+
"compare-stage": "#000000"
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
});
|
|
1
1468
|
// src/core/spring.ts
|
|
2
1469
|
class Spring {
|
|
3
1470
|
x;
|
|
@@ -81,13 +1548,20 @@ function springCss(value) {
|
|
|
81
1548
|
}
|
|
82
1549
|
|
|
83
1550
|
// src/core/theme.ts
|
|
84
|
-
var
|
|
1551
|
+
var property = (k) => k.startsWith("--") ? k : `--k-${k}`;
|
|
85
1552
|
function presetCss(preset) {
|
|
86
1553
|
if (!/^[\w-]+$/.test(preset.name))
|
|
87
1554
|
throw new Error(`Invalid preset name: ${preset.name}`);
|
|
88
|
-
const at = `.knobs-
|
|
89
|
-
const light = preset.light
|
|
90
|
-
|
|
1555
|
+
const at = `.knobs-root[data-preset="${preset.name}"]`;
|
|
1556
|
+
const light = preset.light ?? {};
|
|
1557
|
+
const decls = Object.entries(preset.dark).map(([k, dark]) => {
|
|
1558
|
+
const l = light[k];
|
|
1559
|
+
return l === undefined || String(l) === String(dark) ? `${property(k)}:${dark}` : `${property(k)}:light-dark(${l},${dark})`;
|
|
1560
|
+
});
|
|
1561
|
+
for (const [k, l] of Object.entries(light))
|
|
1562
|
+
if (!(k in preset.dark) && k !== "color-scheme")
|
|
1563
|
+
decls.push(`${property(k)}:${l}`);
|
|
1564
|
+
return `${at}{${decls.join(";")}}${(preset.css ?? "").replaceAll("&", at)}`;
|
|
91
1565
|
}
|
|
92
1566
|
var glide = /* @__PURE__ */ springCss({ duration: 0.185, bounce: 0.14 });
|
|
93
1567
|
var labPreset = {
|
|
@@ -127,6 +1601,7 @@ var labPreset = {
|
|
|
127
1601
|
glass: 0,
|
|
128
1602
|
glow: 0,
|
|
129
1603
|
lift: 0,
|
|
1604
|
+
"lift-shadow": "none",
|
|
130
1605
|
blur: 0.6,
|
|
131
1606
|
"hover-in": 0,
|
|
132
1607
|
"hover-out": 120,
|
|
@@ -145,6 +1620,27 @@ var labPreset = {
|
|
|
145
1620
|
"disabled-opacity": 0.38,
|
|
146
1621
|
"curve-guide": "dashed",
|
|
147
1622
|
"curve-dot": 0
|
|
1623
|
+
},
|
|
1624
|
+
light: {
|
|
1625
|
+
bg: "#f5f5f7",
|
|
1626
|
+
page: "#e6e6eb",
|
|
1627
|
+
surface: "rgba(0,0,0,calc(.05 * var(--k-contrast,1)))",
|
|
1628
|
+
"surface-hi": "rgba(0,0,0,calc(.095 * var(--k-contrast,1)))",
|
|
1629
|
+
line: "rgba(0,0,0,calc(.1 * var(--k-contrast,1)))",
|
|
1630
|
+
"line-hi": "rgba(0,0,0,calc(.2 * var(--k-contrast,1)))",
|
|
1631
|
+
text: "rgba(0,0,0,.88)",
|
|
1632
|
+
label: "rgba(60,60,67,.68)",
|
|
1633
|
+
dim: "rgba(60,60,67,.5)",
|
|
1634
|
+
accent: "#2f6fe4",
|
|
1635
|
+
modified: "#2f6fe4",
|
|
1636
|
+
"seg-bg": "rgba(0,0,0,.065)",
|
|
1637
|
+
"seg-active": "#fff",
|
|
1638
|
+
"toggle-track": "rgba(0,0,0,.14)",
|
|
1639
|
+
"toggle-thumb": "#fff",
|
|
1640
|
+
thumb: "#fff",
|
|
1641
|
+
rim: "transparent",
|
|
1642
|
+
"group-color": "rgba(60,60,67,.68)",
|
|
1643
|
+
"group-divider": "rgba(0,0,0,.1)"
|
|
148
1644
|
}
|
|
149
1645
|
};
|
|
150
1646
|
var problemsPreset = {
|
|
@@ -224,12 +1720,18 @@ var problemsPreset = {
|
|
|
224
1720
|
"toggle-thumb": "#fff",
|
|
225
1721
|
rim: "transparent",
|
|
226
1722
|
"group-color": "rgba(60,60,67,.66)",
|
|
227
|
-
"group-divider": "rgba(0,0,0,.07)"
|
|
228
|
-
"color-scheme": "light"
|
|
1723
|
+
"group-divider": "rgba(0,0,0,.07)"
|
|
229
1724
|
}
|
|
230
1725
|
};
|
|
1726
|
+
// src/themes/index.ts
|
|
1727
|
+
var themes = { knobs, void: voidTheme };
|
|
231
1728
|
export {
|
|
1729
|
+
APCA_BUDGET,
|
|
1730
|
+
defineTheme,
|
|
1731
|
+
knobs,
|
|
232
1732
|
labPreset,
|
|
233
1733
|
presetCss,
|
|
234
|
-
problemsPreset
|
|
1734
|
+
problemsPreset,
|
|
1735
|
+
themes,
|
|
1736
|
+
voidTheme
|
|
235
1737
|
};
|