@cyclone-ui/theme-builder 0.0.4 → 0.0.5

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.
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it } from "vitest";
2
2
 
3
- import { tamaguiPreprocessor } from "./tamagui-preprocessor";
3
+ import { tamaguiPreprocessor } from "../src/preprocessor";
4
4
 
5
5
  const colorToken = (value: string) => ({
6
6
  $type: "color",
@@ -56,41 +56,41 @@ const hueDistance = (first: number, second: number): number => {
56
56
  };
57
57
 
58
58
  describe("tamaguiPreprocessor", () => {
59
- it("generates missing on-* text colors for status colors", () => {
59
+ it("generates missing on-primary text colors for theme color groups", () => {
60
60
  const result = tamaguiPreprocessor({
61
61
  color: {
62
- danger: colorToken("#336699"),
63
- warning: colorToken("#ffee99")
62
+ danger: { primary: colorToken("#336699") },
63
+ warning: { primary: colorToken("#ffee99") }
64
64
  }
65
65
  }) as any;
66
66
 
67
- expect(result.color["on-danger-accent"]).toMatchObject({
67
+ expect(result.color.danger["on-primary"]).toMatchObject({
68
68
  $value: "#FAFAFA",
69
- $description: "Generated text and icon color on danger backgrounds"
69
+ $description:
70
+ "Generated text and icon color on danger primary backgrounds"
70
71
  });
71
- expect(result.color["on-warning-accent"].$value).toBe("#151518");
72
- expect(result.color).not.toHaveProperty("on-danger");
72
+ expect(result.color.warning["on-primary"].$value).toBe("#151518");
73
73
  });
74
74
 
75
- it("generates missing *-muted backgrounds from the parent theme", () => {
75
+ it("generates missing secondary backgrounds from the parent theme", () => {
76
76
  const lightDanger = "#336699";
77
77
  const darkDanger = "#99ccff";
78
78
  const result = tamaguiPreprocessor({
79
79
  light: {
80
80
  color: {
81
81
  $description: "The light theme colors",
82
- danger: colorToken(lightDanger)
82
+ danger: { primary: colorToken(lightDanger) }
83
83
  }
84
84
  },
85
85
  dark: {
86
86
  color: {
87
87
  $description: "The dark theme colors",
88
- danger: colorToken(darkDanger)
88
+ danger: { primary: colorToken(darkDanger) }
89
89
  }
90
90
  }
91
91
  }) as any;
92
- const light = result.light.color["danger-muted"];
93
- const dark = result.dark.color["danger-muted"];
92
+ const light = result.light.color.danger.secondary;
93
+ const dark = result.dark.color.danger.secondary;
94
94
 
95
95
  expect(light.$description).toBe(
96
96
  "Generated low-emphasis danger background for the light theme"
@@ -105,29 +105,34 @@ describe("tamaguiPreprocessor", () => {
105
105
  relativeLuminance(darkDanger)
106
106
  );
107
107
  expect(
108
- contrastRatio(light.$value, result.light.color["on-danger-muted"].$value)
109
- ).toBeGreaterThanOrEqual(6.6);
108
+ contrastRatio(
109
+ light.$value,
110
+ result.light.color.danger["on-secondary"].$value
111
+ )
112
+ ).toBeGreaterThanOrEqual(7.25);
110
113
  });
111
114
 
112
- it("preserves explicit on-* and *-muted colors and skips primary companions", () => {
115
+ it("preserves explicit companions and skips root colors", () => {
113
116
  const result = tamaguiPreprocessor({
114
117
  color: {
115
118
  $description: "The light theme colors",
116
- primary: colorToken("#336699"),
117
- info: colorToken("#336699"),
118
- "on-info": colorToken("#f0f0f0"),
119
- "info-muted": colorToken("#abcdef")
119
+ emphasis: colorToken("#336699"),
120
+ info: {
121
+ primary: colorToken("#336699"),
122
+ "on-primary": colorToken("#f0f0f0"),
123
+ secondary: colorToken("#abcdef")
124
+ }
120
125
  }
121
126
  }) as any;
122
127
 
123
- expect(result.color["on-info-accent"]).toMatchObject({
128
+ expect(result.color.info["on-primary"]).toMatchObject({
124
129
  $value: "#f0f0f0",
125
130
  theme: "info"
126
131
  });
127
- expect(result.color).not.toHaveProperty("on-info");
128
- expect(result.color["info-muted"].$value).toBe("#abcdef");
129
- expect(result.color).not.toHaveProperty("on-primary");
130
- expect(result.color).not.toHaveProperty("primary-muted");
132
+ expect(result.color.info.secondary.$value).toBe("#abcdef");
133
+ expect(result.color.info["on-secondary"].$value).toBe("#151518");
134
+ expect(result.color).not.toHaveProperty("on-emphasis");
135
+ expect(result.color).not.toHaveProperty("emphasis-active");
131
136
  });
132
137
 
133
138
  it("preserves the status hue when generated colors require gamut mapping", () => {
@@ -136,46 +141,48 @@ describe("tamaguiPreprocessor", () => {
136
141
  light: {
137
142
  color: {
138
143
  $description: "The light theme colors",
139
- danger: colorToken(danger)
144
+ danger: { primary: colorToken(danger) }
140
145
  }
141
146
  },
142
147
  dark: {
143
148
  color: {
144
149
  $description: "The dark theme colors",
145
- danger: colorToken(danger)
150
+ danger: { primary: colorToken(danger) }
146
151
  }
147
152
  }
148
153
  }) as any;
149
154
 
150
155
  for (const color of [
151
- result.light.color["danger-muted"].$value,
152
- result.dark.color["danger-muted"].$value
156
+ result.light.color.danger.secondary.$value,
157
+ result.dark.color.danger.secondary.$value
153
158
  ]) {
154
159
  expect(
155
160
  hueDistance(oklchHue(color), oklchHue(danger))
156
- ).toBeLessThanOrEqual(1);
161
+ ).toBeLessThanOrEqual(1.5);
157
162
  }
158
163
  });
159
164
 
160
- it("resolves status references before generating companions", () => {
165
+ it("resolves primary references before generating companions", () => {
161
166
  const result = tamaguiPreprocessor({
162
167
  palette: { red: colorToken("#336699") },
163
168
  light: {
164
169
  color: {
165
170
  $description: "The light theme colors",
166
- danger: colorToken("{palette.red}")
171
+ danger: { primary: colorToken("{palette.red}") }
167
172
  }
168
173
  }
169
174
  }) as any;
170
175
 
171
- expect(result.light.color["on-danger-accent"].$value).toBe("#FAFAFA");
172
- expect(result.light.color["danger-muted"].$value).toMatch(/^#[0-9a-f]{6}$/);
176
+ expect(result.light.color.danger["on-primary"].$value).toBe("#FAFAFA");
177
+ expect(result.light.color.danger.secondary.$value).toMatch(
178
+ /^#[0-9a-f]{6}$/
179
+ );
173
180
  });
174
181
 
175
182
  it("derives low-saturation states from the contrast primitive and scales saturated colors", () => {
176
183
  const color = {
177
- primary: colorToken("#777777"),
178
- danger: colorToken("#336699")
184
+ base: { primary: colorToken("#777777") },
185
+ danger: { primary: colorToken("#336699") }
179
186
  };
180
187
  const result = tamaguiPreprocessor({
181
188
  dark: { color: { $description: "The dark theme colors", ...color } },
@@ -185,169 +192,155 @@ describe("tamaguiPreprocessor", () => {
185
192
  const light = result.light.color;
186
193
 
187
194
  expect({
188
- darkActive: dark["base-active"].$value,
189
- lightActive: light["base-active"].$value,
190
- darkActiveDescription: dark["base-active"].$description,
191
- darkInactive: dark["base-inactive"].$description,
192
- darkDanger: dark["danger-active"].$description,
193
- lightDanger: light["danger-active"].$description,
194
- dangerInactive: dark["danger-inactive"].$description
195
+ darkActive: dark.base["primary-active"].$value,
196
+ lightActive: light.base["primary-active"].$value,
197
+ darkActiveDescription: dark.base["primary-active"].$description,
198
+ darkInactive: dark.base["primary-inactive"].$description,
199
+ darkDanger: dark.danger["primary-active"].$description,
200
+ lightDanger: light.danger["primary-active"].$description,
201
+ dangerInactive: dark.danger["primary-inactive"].$description
195
202
  }).toEqual({
196
203
  darkActive: "#ffffff",
197
204
  lightActive: "#0c0c0d",
198
205
  darkActiveDescription: "active state at dark contrast primitive",
199
206
  darkInactive: "inactive state at 40% darker",
200
- darkDanger: "active state at 19% brighter",
201
- lightDanger: "active state at 19% darker",
207
+ darkDanger: "active state at 25% brighter",
208
+ lightDanger: "active state at 25% darker",
202
209
  dangerInactive: "inactive state at 20% darker"
203
210
  });
204
211
  });
205
212
 
206
- it("shifts active colors already near the contrast primitive toward the middle", () => {
213
+ it("shifts hovered colors near the contrast primitive toward the middle", () => {
207
214
  const result = tamaguiPreprocessor({
208
215
  dark: {
209
216
  color: {
210
217
  $description: "The dark theme colors",
211
- primary: colorToken("#f1f1f1")
218
+ base: { primary: colorToken("#f1f1f1") }
212
219
  }
213
220
  },
214
221
  light: {
215
222
  color: {
216
223
  $description: "The light theme colors",
217
- primary: colorToken("#1f1f21")
224
+ base: { primary: colorToken("#1f1f21") }
218
225
  }
219
226
  }
220
227
  }) as any;
228
+ const dark = result.dark.color.base;
229
+ const light = result.light.color.base;
221
230
 
222
231
  expect({
223
- dark: result.dark.color["base-active"].$description,
224
- light: result.light.color["base-active"].$description
232
+ darkHovered: dark["primary-hovered"].$description,
233
+ lightHovered: light["primary-hovered"].$description,
234
+ darkActive: dark["primary-active"].$value,
235
+ lightActive: light["primary-active"].$value
225
236
  }).toEqual({
226
- dark: "active state at 10% darker",
227
- light: "active state at 10% lighter"
228
- });
229
- expect(
230
- relativeLuminance(result.dark.color["base-active"].$value)
231
- ).toBeLessThan(relativeLuminance("#f1f1f1"));
232
- expect(
233
- relativeLuminance(result.light.color["base-active"].$value)
234
- ).toBeGreaterThan(relativeLuminance("#1f1f21"));
235
- });
236
-
237
- it("keeps low-saturation surface states subtler than other neutral colors", () => {
238
- const result = tamaguiPreprocessor({
239
- color: {
240
- $description: "The dark theme colors",
241
- primary: colorToken("#333333"),
242
- surface: { canvas: colorToken("#333333") }
243
- }
244
- }) as any;
245
-
246
- expect({
247
- primaryActive: result.color["base-active"].$value,
248
- canvasActive: result.color.surface["canvas-active"].$description,
249
- canvasInactive: result.color.surface["canvas-inactive"].$description
250
- }).toEqual({
251
- primaryActive: "#ffffff",
252
- canvasActive: "active state at 10% brighter",
253
- canvasInactive: "inactive state at 20% darker"
237
+ darkHovered: "hovered state at 25% darker",
238
+ lightHovered: "hovered state at 25% lighter",
239
+ darkActive: "#ffffff",
240
+ lightActive: "#000000"
254
241
  });
242
+ expect(relativeLuminance(dark["primary-hovered"].$value)).toBeLessThan(
243
+ relativeLuminance("#f1f1f1")
244
+ );
245
+ expect(relativeLuminance(light["primary-hovered"].$value)).toBeGreaterThan(
246
+ relativeLuminance("#1f1f21")
247
+ );
255
248
  });
256
249
 
257
- it("increases outline active strength", () => {
250
+ it("increases hairline active strength", () => {
258
251
  const result = tamaguiPreprocessor({
259
- color: {
260
- outline: colorToken("#333333")
261
- }
252
+ color: { hairline: colorToken("#333333") }
262
253
  }) as any;
263
254
  const saturated = tamaguiPreprocessor({
264
- color: { outline: colorToken("#336699") }
255
+ color: { hairline: colorToken("#336699") }
265
256
  }) as any;
266
257
 
267
258
  expect({
268
- outline: result.color["outline-active"].$description,
269
- outlineSaturated: saturated.color["outline-active"].$description
259
+ hairline: result.color["hairline-active"].$description,
260
+ hairlineSaturated: saturated.color["hairline-active"].$description
270
261
  }).toEqual({
271
- outline: "active state at 80% brighter",
272
- outlineSaturated: "active state at 40% brighter"
262
+ hairline: "active state at 80% brighter",
263
+ hairlineSaturated: "active state at 40% brighter"
273
264
  });
265
+ expect(result.color["hairline-active"].group).toBe("hairline");
274
266
  });
275
267
 
276
- it("generates active, inactive, and disabled states only for target colors", () => {
268
+ it("generates hovered, active, inactive, and disabled states only for target colors", () => {
277
269
  const result = tamaguiPreprocessor({
278
270
  color: {
279
- surface: {
280
- sunken: colorToken("#111111"),
281
- canvas: colorToken("#222222")
271
+ sunken: { ...colorToken("#111111"), group: "background" },
272
+ canvas: { ...colorToken("#222222"), group: "background" },
273
+ emphasis: { ...colorToken("#f5f5f5"), group: "foreground" },
274
+ ink: { ...colorToken("#777777"), group: "foreground" },
275
+ subtle: { ...colorToken("#777777"), group: "foreground" },
276
+ subtlest: colorToken("#777777"),
277
+ hairline: colorToken("#777777"),
278
+ base: {
279
+ primary: colorToken("#f5f5f5"),
280
+ secondary: colorToken("#777777")
281
+ },
282
+ danger: {
283
+ primary: colorToken("#ff0000"),
284
+ "on-primary": colorToken("#ffffff"),
285
+ secondary: colorToken("#330000")
282
286
  },
283
- primary: colorToken("#f5f5f5"),
284
- "on-primary": colorToken("#111111"),
285
- secondary: colorToken("#777777"),
286
- tertiary: colorToken("#777777"),
287
- outline: colorToken("#777777"),
288
- danger: colorToken("#ff0000"),
289
- "on-danger": colorToken("#ffffff"),
290
- "danger-muted": colorToken("#330000"),
291
287
  backdrop: colorToken("#00000066"),
292
288
  data: { red: { emphasis: colorToken("#555555") } }
293
289
  }
294
290
  }) as any;
291
+ const states = ["hovered", "active", "inactive", "disabled"];
295
292
 
296
- expect(Object.keys(result.color.surface).sort()).toEqual([
297
- "canvas",
298
- "canvas-active",
299
- "canvas-disabled",
300
- "canvas-inactive",
301
- "sunken",
302
- "sunken-active",
303
- "sunken-disabled",
304
- "sunken-inactive"
305
- ]);
306
- for (const key of [
307
- "base",
308
- "base-muted",
309
- "outline",
310
- "danger",
311
- "danger-muted"
312
- ]) {
313
- for (const state of ["active", "inactive", "disabled"]) {
293
+ for (const group of [result.color.base, result.color.danger]) {
294
+ for (const key of ["primary", "secondary"]) {
295
+ for (const state of states) {
296
+ expect(group).toHaveProperty(`${key}-${state}`);
297
+ }
298
+ }
299
+ expect(group).not.toHaveProperty("on-primary-active");
300
+ expect(group).not.toHaveProperty("on-secondary-active");
301
+ }
302
+ for (const state of states) {
303
+ for (const key of [
304
+ "hairline",
305
+ "emphasis",
306
+ "ink",
307
+ "subtle",
308
+ "sunken",
309
+ "canvas"
310
+ ]) {
314
311
  expect(result.color).toHaveProperty(`${key}-${state}`);
315
312
  }
316
- expect(result.color).not.toHaveProperty(`${key}-hover`);
317
313
  }
314
+ expect(result.color["ink-active"].group).toBe("foreground");
318
315
 
319
- for (const key of ["primary", "secondary", "tertiary", "on-primary"]) {
316
+ for (const key of ["subtlest", "backdrop"]) {
320
317
  expect(result.color).toHaveProperty(key);
321
318
  expect(result.color).not.toHaveProperty(`${key}-active`);
322
319
  }
323
- expect(result.color).not.toHaveProperty("base-accent-active");
324
- expect(result.color).not.toHaveProperty("on-base-accent-active");
325
- expect(result.color).not.toHaveProperty("on-danger-active");
326
- expect(result.color).not.toHaveProperty("backdrop-active");
327
320
  expect(result.color.data.red).not.toHaveProperty("emphasis-active");
328
321
  });
329
322
 
330
323
  it("does not overwrite explicit state colors", () => {
331
324
  const result = tamaguiPreprocessor({
332
325
  color: {
333
- surface: {
334
- canvas: colorToken("#222222"),
335
- "canvas-active": colorToken("#abcdef")
336
- },
337
- outline: colorToken("#336699"),
338
- "outline-active": colorToken("#fedcba")
326
+ hairline: colorToken("#336699"),
327
+ "hairline-active": colorToken("#fedcba"),
328
+ danger: {
329
+ primary: colorToken("#336699"),
330
+ "primary-active": colorToken("#abcdef")
331
+ }
339
332
  }
340
333
  }) as any;
341
334
 
342
- expect(result.color.surface["canvas-active"].$value).toBe("#abcdef");
343
- expect(result.color["outline-active"].$value).toBe("#fedcba");
335
+ expect(result.color["hairline-active"].$value).toBe("#fedcba");
336
+ expect(result.color.danger["primary-active"].$value).toBe("#abcdef");
344
337
  });
345
338
 
346
- it("does not generate states for non-color tokens in target groups", () => {
339
+ it("skips theme color groups whose primary is not a color", () => {
347
340
  const result = tamaguiPreprocessor({
348
341
  color: {
349
- surface: {
350
- shadow: {
342
+ danger: {
343
+ primary: {
351
344
  $type: "shadow",
352
345
  $value: { color: "#336699", offsetX: 0 }
353
346
  }
@@ -355,88 +348,74 @@ describe("tamaguiPreprocessor", () => {
355
348
  }
356
349
  }) as any;
357
350
 
358
- expect(result.color.surface).not.toHaveProperty("shadow-active");
359
- expect(result.color.surface.shadow.$value.color).toBe("#336699");
351
+ expect(result.color.danger).not.toHaveProperty("primary-active");
352
+ expect(result.color.danger).not.toHaveProperty("on-primary");
353
+ expect(result.color.danger.primary.$value.color).toBe("#336699");
360
354
  });
361
355
 
362
356
  it("desaturates colored disabled variants and fades them over the disabled base", () => {
363
357
  const result = tamaguiPreprocessor({
364
- color: { danger: colorToken("#ff000080") }
358
+ color: { danger: { primary: colorToken("#ff000080") } }
365
359
  }) as any;
366
360
 
367
- expect(result.color["danger-disabled"]).toMatchObject({
361
+ expect(result.color.danger["primary-disabled"]).toMatchObject({
368
362
  $description:
369
- "disabled state at 85% saturation, 13% over oklch(0.3839 0.0045 286.26)",
363
+ "disabled state at 85% saturation, 35% over oklch(0.3839 0.0045 286.26)",
370
364
  $value: expect.stringMatching(/^#[0-9a-f]{6}$/)
371
365
  });
372
366
  });
373
367
 
374
- it("fades greyscale surface disabled variants over the disabled base", () => {
375
- const result = tamaguiPreprocessor({
376
- color: { surface: { canvas: colorToken("#ffffff") } }
377
- }) as any;
378
-
379
- expect(result.color.surface["canvas-disabled"]).toMatchObject({
380
- $description: "disabled state at 13% over oklch(0.3839 0.0045 286.26)",
381
- $value: "#5b5b5d"
382
- });
383
- });
384
-
385
- it("assigns themes to base aliases and status colors", () => {
368
+ it("assigns the group name as theme and group to theme color tokens", () => {
386
369
  const result = tamaguiPreprocessor({
387
370
  color: {
388
371
  $description: "The dark theme colors",
389
- primary: colorToken("#eeeeee"),
390
- "on-primary": colorToken("#111111"),
391
- tertiary: { ...colorToken("#444444"), theme: "custom" },
392
- outline: colorToken("#777777"),
393
- warning: colorToken("#ffee99")
372
+ emphasis: colorToken("#eeeeee"),
373
+ hairline: colorToken("#777777"),
374
+ base: {
375
+ primary: colorToken("#eeeeee"),
376
+ "on-primary": colorToken("#111111"),
377
+ secondary: { ...colorToken("#444444"), theme: "custom" }
378
+ },
379
+ warning: { primary: colorToken("#ffee99") }
394
380
  }
395
381
  }) as any;
382
+ const { base, warning } = result.color;
396
383
 
397
- expect(result.color.primary.theme).toBeUndefined();
398
- expect(result.color["on-primary"].theme).toBeUndefined();
399
- expect(result.color.base).toMatchObject({
384
+ expect(result.color.emphasis.theme).toBeUndefined();
385
+ expect(result.color.hairline.theme).toBeUndefined();
386
+ expect(base.primary).toMatchObject({
400
387
  $value: "#eeeeee",
401
388
  theme: "base",
402
389
  group: "base"
403
390
  });
404
- expect(result.color["base-accent"]).toMatchObject({
405
- $value: "{color.base}",
406
- theme: "base"
407
- });
408
- expect(result.color["base-active"].theme).toBe("base");
409
- expect(result.color).not.toHaveProperty("on-base");
410
- expect(result.color["on-base-accent"]).toMatchObject({
391
+ expect(base["on-primary"]).toMatchObject({
411
392
  $value: "#111111",
412
393
  theme: "base"
413
394
  });
414
- expect(result.color.tertiary.theme).toBe("custom");
415
- expect(result.color).not.toHaveProperty("tertiary-disabled");
416
- expect(result.color.outline.theme).toBeUndefined();
417
- expect(result.color.warning.theme).toBe("warning");
418
- expect(result.color["warning-accent"]).toMatchObject({
419
- $value: "{color.warning}",
420
- theme: "warning",
421
- group: "warning"
422
- });
423
- expect(result.color["on-warning-accent"]).toMatchObject({
424
- theme: "warning",
425
- group: "warning"
426
- });
427
- expect(result.color["on-warning-muted"].theme).toBe("warning");
428
- expect(result.color["warning-muted"].theme).toBe("warning");
429
- expect(result.color["warning-muted-active"].theme).toBe("warning");
430
- expect(result.color["warning-inactive"].theme).toBe("warning");
395
+ expect(base["primary-active"].theme).toBe("base");
396
+ expect(base.secondary.theme).toBe("custom");
397
+ for (const key of [
398
+ "primary",
399
+ "on-primary",
400
+ "secondary",
401
+ "on-secondary",
402
+ "secondary-active",
403
+ "primary-inactive"
404
+ ]) {
405
+ expect(warning[key]).toMatchObject({
406
+ theme: "warning",
407
+ group: "warning"
408
+ });
409
+ }
431
410
  });
432
411
 
433
- it("generates focus rings for base aliases and status colors", () => {
412
+ it("generates focus rings for theme color groups", () => {
434
413
  const result = tamaguiPreprocessor({
435
414
  color: {
436
- surface: { elevated: colorToken("#222222") },
437
- primary: colorToken("#eeeeee"),
438
- outline: colorToken("#777777"),
439
- danger: colorToken("#336699")
415
+ elevated: { ...colorToken("#222222"), group: "background" },
416
+ emphasis: colorToken("#eeeeee"),
417
+ base: { primary: colorToken("#eeeeee") },
418
+ danger: { primary: colorToken("#336699") }
440
419
  }
441
420
  }) as any;
442
421
 
@@ -453,12 +432,12 @@ describe("tamaguiPreprocessor", () => {
453
432
  expect(result.ring["base-offset"]).toMatchObject({ theme: "base" });
454
433
  expect(result.ring.base).toMatchObject({
455
434
  theme: "base",
456
- $value: [{ color: "#eeeeee14", spread: { value: 3, unit: "px" } }]
435
+ $value: [{ color: "#eeeeee1a", spread: { value: 3, unit: "px" } }]
457
436
  });
458
437
  expect(result.ring["danger-offset"]).toMatchObject({
459
438
  theme: "danger",
460
439
  $value: [
461
- { color: "{color.surface-elevated}" },
440
+ { color: "{color.elevated}" },
462
441
  { color: "#33669926", spread: { value: 6, unit: "px" } }
463
442
  ]
464
443
  });
@@ -503,7 +482,7 @@ describe("tamaguiPreprocessor", () => {
503
482
  expect(result).toMatchObject({
504
483
  semantic: {
505
484
  ring: {
506
- neutral: { $value: { color: "#77777714" } },
485
+ neutral: { $value: { color: "#7777771a" } },
507
486
  saturated: { $value: { color: "#33669926" } },
508
487
  layered: {
509
488
  $value: [{ color: "#ff0000" }, { color: "#00ff0026" }]
@@ -62,24 +62,21 @@ const color = ($value: string): Token => ({ $value });
62
62
 
63
63
  const semanticColors = (prefix: string) => ({
64
64
  color: {
65
- primary: color(`${prefix}-primary`),
66
- secondary: color(`${prefix}-secondary`),
67
- tertiary: color(`${prefix}-tertiary`),
68
- border: color(`${prefix}-border`),
69
- "surface-canvas": color(`${prefix}-surface-canvas`),
70
- "surface-sunken": color(`${prefix}-surface-sunken`),
71
- danger: color(`${prefix}-danger`),
72
- warning: color(`${prefix}-warning`),
73
- success: color(`${prefix}-success`),
74
- info: color(`${prefix}-info`),
75
- discovery: color(`${prefix}-discovery`)
76
- }
65
+ emphasis: color(`${prefix}-emphasis`),
66
+ ink: color(`${prefix}-ink`),
67
+ subtle: color(`${prefix}-subtle`),
68
+ hairline: color(`${prefix}-hairline`),
69
+ canvas: color(`${prefix}-canvas`),
70
+ sunken: color(`${prefix}-sunken`),
71
+ danger: { primary: color(`${prefix}-danger`) },
72
+ warning: { primary: color(`${prefix}-warning`) },
73
+ success: { primary: color(`${prefix}-success`) },
74
+ info: { primary: color(`${prefix}-info`) },
75
+ discovery: { primary: color(`${prefix}-discovery`) }
76
+ } as Record<string, unknown>
77
77
  });
78
78
 
79
- const setting = (
80
- theme: MappedTheme,
81
- scope: string
82
- ) =>
79
+ const setting = (theme: MappedTheme, scope: string) =>
83
80
  theme.settings.find(candidate => candidate.scope.includes(scope))?.settings
84
81
  .foreground;
85
82
 
@@ -107,17 +104,17 @@ describe("Shiki theme mapping", () => {
107
104
  tokens: semanticColors("light")
108
105
  }) as MappedTheme;
109
106
 
110
- expect(dark.fg).toBe("dark-primary");
107
+ expect(dark.fg).toBe("dark-emphasis");
111
108
  expect(dark.colors).toMatchObject({
112
- "editor.background": "dark-surface-canvas",
109
+ "editor.background": "dark-canvas",
113
110
  "editorCursor.foreground": "dark-info",
114
- "editor.selectionBackground": "dark-primary",
115
- "editor.selectionForeground": "dark-surface-canvas",
116
- "editor.inactiveSelectionBackground": "dark-surface-sunken",
117
- "editorIndentGuide.background1": "dark-border",
118
- "editorIndentGuide.activeBackground1": "dark-tertiary"
111
+ "editor.selectionBackground": "dark-emphasis",
112
+ "editor.selectionForeground": "dark-canvas",
113
+ "editor.inactiveSelectionBackground": "dark-sunken",
114
+ "editorIndentGuide.background1": "dark-hairline",
115
+ "editorIndentGuide.activeBackground1": "dark-subtle"
119
116
  });
120
- expect(setting(dark, "comment")).toBe("dark-tertiary");
117
+ expect(setting(dark, "comment")).toBe("dark-subtle");
121
118
  expect(setting(dark, "string")).toBe("dark-success");
122
119
  expect(setting(dark, "constant")).toBe("dark-warning");
123
120
  expect(setting(dark, "keyword")).toBe("dark-info");
@@ -126,8 +123,8 @@ describe("Shiki theme mapping", () => {
126
123
  expect(setting(dark, "entity.other.attribute-name")).toBe("dark-info");
127
124
  expect(setting(dark, "invalid")).toBe("dark-danger");
128
125
 
129
- expect(light.fg).toBe("light-primary");
130
- expect(light.colors["editor.background"]).toBe("light-surface-canvas");
126
+ expect(light.fg).toBe("light-emphasis");
127
+ expect(light.colors["editor.background"]).toBe("light-canvas");
131
128
  expect(setting(light, "string")).toBe("light-success");
132
129
  });
133
130
 
@@ -144,7 +141,7 @@ describe("Shiki theme mapping", () => {
144
141
  );
145
142
  const tokens = semanticColors("light");
146
143
 
147
- tokens.color.tertiary = color("{color.neutral.7}");
144
+ tokens.color.subtle = color("{color.neutral.7}");
148
145
  Object.assign(tokens.color, {
149
146
  neutral: { 7: color("#959698") }
150
147
  });