Skip to content

Commit d7858f7

Browse files
committed
Add new CSS value creation functions and corresponding tests
1 parent c3aa62f commit d7858f7

4 files changed

Lines changed: 185 additions & 2 deletions

File tree

README.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,61 @@ serialize(pow(2, 3)); // "pow(2,3)"
111111
serialize(pow("var(--base)", "2")); // "pow(var(--base),2)"
112112
```
113113

114+
#### `var(name, fallback?)`
115+
116+
Creates a `var()` expression for CSS custom properties.
117+
118+
```typescript
119+
import { add, var as cssVar } from "@dldc/css-builder";
120+
121+
serialize(cssVar("--space")); // "var(--space)"
122+
serialize(cssVar("--gutter", add("8px", 2))); // "var(--gutter,8px + 2)"
123+
```
124+
125+
#### `number(value)`
126+
127+
Creates a numeric calc value.
128+
129+
```typescript
130+
serialize(number(42)); // "42"
131+
serialize(number("3.14")); // "3.14"
132+
```
133+
134+
#### `dimension(value, unit)`
135+
136+
Creates a dimension calc value.
137+
138+
```typescript
139+
serialize(dimension(10, "px")); // "10px"
140+
serialize(dimension("1.5", "rem")); // "1.5rem"
141+
```
142+
143+
#### `percentage(value)`
144+
145+
Creates a percentage calc value.
146+
147+
```typescript
148+
serialize(percentage(50)); // "50%"
149+
serialize(percentage("12.5")); // "12.5%"
150+
```
151+
152+
#### `raw(value)`
153+
154+
Creates a raw calc value (no parsing).
155+
156+
```typescript
157+
serialize(raw("var(--size)")); // "var(--size)"
158+
```
159+
160+
#### `group(value)`
161+
162+
Wraps a value or sum in parentheses, useful for preserving precedence in
163+
composed expressions.
164+
165+
```typescript
166+
serialize(group(value("10px"))); // "(10px)"
167+
```
168+
114169
#### `round(...)`
115170

116171
Creates a `round()` expression. You can pass a rounding strategy as the first

src/builder.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,3 +404,64 @@ export function value(value: string | number): Ast.CalcValue {
404404
}
405405
return create.calcValue.dimension(numberPart, unit);
406406
}
407+
408+
/**
409+
* Creates a CSS var() function expression.
410+
* @param name - The custom property name (for example, '--spacing')
411+
* @param fallback - Optional fallback value if the custom property is not defined
412+
* @returns A Var AST node representing var(name[, fallback])
413+
*/
414+
function variable(name: string, fallback?: AnyExpression): Ast.Var {
415+
return create.calcValue.var(
416+
name,
417+
fallback ? anyExprToCalcSum(fallback) : undefined,
418+
);
419+
}
420+
421+
export { variable as var };
422+
423+
/**
424+
* Creates a numeric CalcValue node.
425+
* @param value - A number or numeric string
426+
* @returns A CalcValue number node
427+
*/
428+
export function number(value: number | string): Ast.CalcValue {
429+
return create.calcValue.number(value);
430+
}
431+
432+
/**
433+
* Creates a dimension CalcValue node.
434+
* @param value - A number or numeric string
435+
* @param unit - The dimension unit (for example, 'px', 'rem', 'vw')
436+
* @returns A CalcValue dimension node
437+
*/
438+
export function dimension(value: number | string, unit: string): Ast.CalcValue {
439+
return create.calcValue.dimension(value, unit);
440+
}
441+
442+
/**
443+
* Creates a percentage CalcValue node.
444+
* @param value - A number or numeric string
445+
* @returns A CalcValue percentage node
446+
*/
447+
export function percentage(value: number | string): Ast.CalcValue {
448+
return create.calcValue.percentage(value);
449+
}
450+
451+
/**
452+
* Creates a raw/unprocessed CalcValue node.
453+
* @param value - Raw CSS text to embed directly
454+
* @returns A raw CalcValue node
455+
*/
456+
export function raw(value: string): Ast.CalcValue {
457+
return create.calcValue.raw(value);
458+
}
459+
460+
/**
461+
* Groups a CalcSum in parentheses to preserve precedence.
462+
* @param value - The CalcSum to group
463+
* @returns A grouped CalcValue node
464+
*/
465+
export function group(value: Ast.CalcSum): Ast.CalcValue {
466+
return create.calcValue.group(value);
467+
}

src/create.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ export type CalcValueCreators = {
238238
/** Creates a raw/unprocessed CalcValue */
239239
raw(value: string): Ast.CalcValue;
240240
/** Creates a var() custom property CalcValue */
241-
var(name: string, fallback?: Ast.CalcSum): Ast.CalcValue;
241+
var(name: string, fallback?: Ast.CalcSum): Ast.Var;
242242
};
243243

244244
/**
@@ -295,7 +295,7 @@ export const calcValue: CalcValueCreators = {
295295
};
296296
},
297297
/** @param name The custom property name (e.g., '--my-var') @param fallback Optional fallback value */
298-
var(name: string, fallback?: Ast.CalcSum): Ast.CalcValue {
298+
var(name: string, fallback?: Ast.CalcSum): Ast.Var {
299299
return {
300300
kind: "var",
301301
value: [

tests/builder.test.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,3 +428,70 @@ Deno.test("value", async (t) => {
428428
expect(serialize(builder.value("var(--size)"))).toBe("var(--size)");
429429
});
430430
});
431+
432+
Deno.test("var", async (t) => {
433+
await t.step("creates var without fallback", () => {
434+
const result = builder.var("--space");
435+
expect(serialize(result)).toBe("var(--space)");
436+
});
437+
438+
await t.step("creates var with primitive fallback", () => {
439+
const result = builder.var("--gutter", "10px");
440+
expect(serialize(result)).toBe("var(--gutter,10px)");
441+
});
442+
443+
await t.step("creates var with calc fallback", () => {
444+
const result = builder.var("--size", builder.add("8px", 2));
445+
expect(serialize(result)).toBe("var(--size,8px + 2)");
446+
});
447+
});
448+
449+
Deno.test("number", async (t) => {
450+
await t.step("creates number from numeric value", () => {
451+
expect(serialize(builder.number(42))).toBe("42");
452+
});
453+
454+
await t.step("creates number from string value", () => {
455+
expect(serialize(builder.number("3.14"))).toBe("3.14");
456+
});
457+
});
458+
459+
Deno.test("dimension", async (t) => {
460+
await t.step("creates dimension from numeric value", () => {
461+
expect(serialize(builder.dimension(10, "px"))).toBe("10px");
462+
});
463+
464+
await t.step("creates dimension from string value", () => {
465+
expect(serialize(builder.dimension("1.5", "rem"))).toBe("1.5rem");
466+
});
467+
});
468+
469+
Deno.test("percentage", async (t) => {
470+
await t.step("creates percentage from numeric value", () => {
471+
expect(serialize(builder.percentage(50))).toBe("50%");
472+
});
473+
474+
await t.step("creates percentage from string value", () => {
475+
expect(serialize(builder.percentage("12.5"))).toBe("12.5%");
476+
});
477+
});
478+
479+
Deno.test("raw", async (t) => {
480+
await t.step("creates raw value", () => {
481+
expect(serialize(builder.raw("var(--size)"))).toBe("var(--size)");
482+
});
483+
});
484+
485+
Deno.test("group", async (t) => {
486+
await t.step("groups a value", () => {
487+
expect(serialize(builder.group(builder.value("10px")))).toBe("(10px)");
488+
});
489+
490+
await t.step("groups a calc sum", () => {
491+
const sum = create.calcSum(builder.value("10px"), [
492+
"+",
493+
builder.value("5px"),
494+
]);
495+
expect(serialize(builder.group(sum))).toBe("(10px + 5px)");
496+
});
497+
});

0 commit comments

Comments
 (0)