Skip to content

Commit 236463b

Browse files
committed
Fix: theme - composite value
1 parent 60c2a59 commit 236463b

File tree

1 file changed

+89
-30
lines changed

1 file changed

+89
-30
lines changed

packages/css/src/theme/index.ts

Lines changed: 89 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ interface CSSVarMap {
104104
}
105105

106106
function assignTokens<ThemeTokens extends Theme>(
107-
tokens: ThemeTokens
107+
tokens: ThemeTokensInput<ThemeTokens>
108108
): {
109109
vars: AssignedVars;
110110
resolvedTokens: ResolveTheme<ThemeTokens>;
@@ -259,9 +259,7 @@ function assignTokenVariables(
259259
// Handle TokenCompositeValue
260260
if (isTokenCompositeValue(value)) {
261261
const resolvedComposite: Record<string, PureCSSVarFunction> = {};
262-
263-
// Process resolved property
264-
vars[cssVar] = extractCSSValue(value.resolved);
262+
const compositeDescriptors = Object.getOwnPropertyDescriptors(value);
265263

266264
// Create getter for resolved property
267265
Object.defineProperty(resolvedComposite, "resolved", {
@@ -273,12 +271,20 @@ function assignTokenVariables(
273271
});
274272

275273
// Process other properties
276-
for (const [propKey, propValue] of Object.entries(value)) {
274+
for (const [propKey, propDescriptor] of Object.entries(
275+
compositeDescriptors
276+
)) {
277277
if (propKey === "resolved") continue;
278278

279279
const propPath = `${varPath}-${camelToKebab(propKey)}`;
280280
const propCssVar = getCSSVarByPath(propPath, context);
281-
vars[propCssVar] = extractCSSValue(propValue as TokenValue);
281+
if (typeof propDescriptor.get === "function") {
282+
// Store placeholder reference; value will be resolved in pass 2
283+
resolvedComposite[propKey] = getVarReference(propPath, context);
284+
continue;
285+
}
286+
287+
vars[propCssVar] = extractCSSValue(propDescriptor.value as TokenValue);
282288
resolvedComposite[propKey] = getVarReference(propPath, context);
283289
}
284290

@@ -353,6 +359,39 @@ function resolveSemanticTokens(
353359

354360
const value = descriptor.value;
355361

362+
// Handle TokenCompositeValue resolved property computation
363+
if (isTokenCompositeValue(value)) {
364+
const compositeDescriptors = Object.getOwnPropertyDescriptors(value);
365+
const resolvedDescriptor = compositeDescriptors.resolved;
366+
367+
if (resolvedDescriptor?.get) {
368+
const resolvedPath = [...currentPath, "resolved"];
369+
const evaluationContext = Object.create(resolvedTokens);
370+
371+
for (const [propKey, propDescriptor] of Object.entries(
372+
compositeDescriptors
373+
)) {
374+
if (propKey === "resolved") continue;
375+
Object.defineProperty(evaluationContext, propKey, propDescriptor);
376+
}
377+
378+
currentProcessingPath = resolvedPath;
379+
const computedValue = resolvedDescriptor.get.call(evaluationContext);
380+
currentProcessingPath = [];
381+
382+
const resolvedPathKey = resolvedPath.join(".");
383+
384+
if (context.aliasMap.has(resolvedPathKey)) {
385+
setByPath(resolvedTokens, resolvedPath, computedValue);
386+
} else {
387+
const cssVar = getCSSVarByPath(varPath, context);
388+
vars[cssVar] = extractCSSValue(computedValue as TokenValue);
389+
}
390+
}
391+
392+
continue;
393+
}
394+
356395
// Handle nested TokenDefinition with object $value
357396
if (
358397
isTokenDefinition(value) &&
@@ -689,9 +728,9 @@ if (import.meta.vitest) {
689728
const debugId = "myCSS";
690729
setFileScope("test");
691730

692-
function composedValue<ComposedValue>(
693-
value: ComposedValue & ThisType<ComposedValue & ThemeSubFunctions>
694-
): ComposedValue {
731+
function compositeValue<CompositeValue>(
732+
value: CompositeValue & ThisType<CompositeValue & ThemeSubFunctions>
733+
): CompositeValue {
695734
return value;
696735
}
697736

@@ -893,7 +932,7 @@ if (import.meta.vitest) {
893932

894933
it("handles semantic token references with getters", () => {
895934
const result = assignTokens(
896-
composedValue({
935+
compositeValue({
897936
color: {
898937
base: {
899938
red: "#ff0000",
@@ -941,7 +980,7 @@ if (import.meta.vitest) {
941980

942981
it("handles fallbackVar in semantic tokens", () => {
943982
const result = assignTokens(
944-
composedValue({
983+
compositeValue({
945984
color: {
946985
base: {
947986
blue: "#0000ff",
@@ -975,7 +1014,7 @@ if (import.meta.vitest) {
9751014

9761015
it("handles alias references in semantic tokens", () => {
9771016
const result = assignTokens(
978-
composedValue({
1017+
compositeValue({
9791018
color: {
9801019
base: {
9811020
blue: "#0000ff",
@@ -1032,7 +1071,7 @@ if (import.meta.vitest) {
10321071

10331072
it("handles raw value extraction in semantic tokens", () => {
10341073
const result = assignTokens(
1035-
composedValue({
1074+
compositeValue({
10361075
color: {
10371076
base: {
10381077
blue: "#0000ff",
@@ -1346,27 +1385,27 @@ if (import.meta.vitest) {
13461385
});
13471386

13481387
it("handles TokenComposedValue with resolved getter", () => {
1349-
const shadowValue = composedValue({
1350-
get resolved() {
1351-
return `${this.color} ${this.offsetX.value}${this.offsetX.unit} ${this.offsetY.value}${this.offsetY.unit} ${this.blur.value}${this.blur.unit}`;
1352-
},
1353-
color: "#00000080",
1354-
offsetX: { value: 0.5, unit: "rem" },
1355-
offsetY: { value: 0.5, unit: "rem" },
1356-
blur: { value: 1.5, unit: "rem" }
1357-
});
1358-
13591388
const result = assignTokens({
13601389
shadow: {
1361-
light: shadowValue
1390+
light: {
1391+
get resolved(): string {
1392+
return `${this.shadow.light.color} ${this.shadow.light.offsetX} ${this.shadow.light.offsetY} ${this.shadow.light.blur}`;
1393+
},
1394+
color: "#00000080",
1395+
offsetX: { value: 0.5, unit: "rem" },
1396+
offsetY: { value: 0.5, unit: "rem" },
1397+
blur: { value: 1.5, unit: "rem" }
1398+
}
13621399
}
13631400
});
13641401

13651402
validateHashFormatForVar(result.vars);
13661403
validateHashFormatForResolved(result.resolvedTokens);
13671404

13681405
const normalized = normalizeVars(result.vars);
1369-
expect(normalized["--shadow-light"]).toMatch(/^#00000080/);
1406+
expect(stripHash(normalized["--shadow-light"])).toBe(
1407+
"var(--shadow-light-color) var(--shadow-light-offset-x) var(--shadow-light-offset-y) var(--shadow-light-blur)"
1408+
);
13701409
expect(normalized["--shadow-light-color"]).toBe("#00000080");
13711410
expect(normalized["--shadow-light-offset-x"]).toBe("0.5rem");
13721411
expect(normalized["--shadow-light-offset-y"]).toBe("0.5rem");
@@ -1565,7 +1604,7 @@ if (import.meta.vitest) {
15651604

15661605
it("handles semantic tokens with fallbackVar", () => {
15671606
const [className, themeVars] = theme(
1568-
composedValue({
1607+
compositeValue({
15691608
color: {
15701609
base: {
15711610
blue: "#0000ff"
@@ -1597,7 +1636,7 @@ if (import.meta.vitest) {
15971636

15981637
it("handles semantic tokens with alias", () => {
15991638
const [className, themeVars] = theme(
1600-
composedValue({
1639+
compositeValue({
16011640
color: {
16021641
base: {
16031642
blue: "#0000ff",
@@ -1626,7 +1665,7 @@ if (import.meta.vitest) {
16261665

16271666
it("handles semantic tokens with raw", () => {
16281667
const [className, themeVars] = theme(
1629-
composedValue({
1668+
compositeValue({
16301669
color: {
16311670
base: {
16321671
blue: "#0000ff",
@@ -1663,7 +1702,7 @@ if (import.meta.vitest) {
16631702
});
16641703

16651704
it("handles TokenCompositeValue", () => {
1666-
const shadowValue = composedValue({
1705+
const shadowValue = compositeValue({
16671706
get resolved() {
16681707
return `${this.color} ${this.offsetX.value}${this.offsetX.unit} ${this.offsetY.value}${this.offsetY.unit}`;
16691708
},
@@ -1781,7 +1820,7 @@ if (import.meta.vitest) {
17811820

17821821
it("handles complex semantic token references", () => {
17831822
const [className, themeVars] = theme(
1784-
composedValue({
1823+
compositeValue({
17851824
color: {
17861825
base: {
17871826
red: "#ff0000",
@@ -1935,6 +1974,17 @@ if (import.meta.vitest) {
19351974
return this.space.base[5];
19361975
}
19371976
}
1977+
},
1978+
shadow: {
1979+
light: {
1980+
get resolved(): string {
1981+
return `${this.shadow.light.color} ${this.shadow.light.offsetX} ${this.shadow.light.offsetY} ${this.shadow.light.blur}`;
1982+
},
1983+
color: "#00000080",
1984+
offsetX: { value: 0.5, unit: "rem" },
1985+
offsetY: { value: 0.5, unit: "rem" },
1986+
blur: { value: 1.5, unit: "rem" }
1987+
}
19381988
}
19391989
},
19401990
debugId
@@ -1969,6 +2019,15 @@ if (import.meta.vitest) {
19692019
medium: "var(--space-base-3)",
19702020
large: "var(--space-base-5)"
19712021
}
2022+
},
2023+
shadow: {
2024+
light: {
2025+
resolved: "var(--shadow-light)",
2026+
color: "var(--shadow-light-color)",
2027+
offsetX: "var(--shadow-light-offset-x)",
2028+
offsetY: "var(--shadow-light-offset-y)",
2029+
blur: "var(--shadow-light-blur)"
2030+
}
19722031
}
19732032
});
19742033
});

0 commit comments

Comments
 (0)