Skip to content

Commit f39678d

Browse files
committed
fix: auto property type
1 parent 814a479 commit f39678d

File tree

8 files changed

+98
-43
lines changed

8 files changed

+98
-43
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@tenphi/tasty': patch
3+
---
4+
5+
Upgrade auto-inferred `@property` types: length and percentage values now register as `<length-percentage>` instead of separate `<length>`/`<percentage>`, enabling smooth transitions between mixed units. Add name-based inference for `--*-line-height` properties as `<number> | <length-percentage>`.

src/properties/index.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -343,9 +343,9 @@ const ANGLE_UNITS = ['deg', 'rad', 'grad', 'turn'];
343343
const TIME_UNITS = ['ms', 's'];
344344

345345
for (const u of LENGTH_UNITS) {
346-
UNIT_TO_SYNTAX[u] = { syntax: '<length>', initialValue: '0px' };
346+
UNIT_TO_SYNTAX[u] = { syntax: '<length-percentage>', initialValue: '0px' };
347347
}
348-
UNIT_TO_SYNTAX['%'] = { syntax: '<percentage>', initialValue: '0%' };
348+
UNIT_TO_SYNTAX['%'] = { syntax: '<length-percentage>', initialValue: '0px' };
349349
for (const u of ANGLE_UNITS) {
350350
UNIT_TO_SYNTAX[u] = { syntax: '<angle>', initialValue: '0deg' };
351351
}
@@ -355,7 +355,8 @@ for (const u of TIME_UNITS) {
355355

356356
/**
357357
* Infer CSS @property syntax from a concrete value.
358-
* Only detects numeric types: \<number\>, \<length\>, \<percentage\>, \<angle\>, \<time\>.
358+
* Detects numeric types: \<number\>, \<length-percentage\>, \<angle\>, \<time\>.
359+
* Length and percentage values both map to \<length-percentage\> for maximum flexibility.
359360
* Color properties are handled separately via the #name token convention
360361
* (--name-color gets \<color\> syntax automatically in getEffectiveDefinition).
361362
*

src/properties/properties.test.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -319,29 +319,29 @@ describe('properties', () => {
319319
});
320320
});
321321

322-
it('should infer <length> from length units', () => {
322+
it('should infer <length-percentage> from length units', () => {
323323
expect(inferSyntaxFromValue('10px')).toEqual({
324-
syntax: '<length>',
324+
syntax: '<length-percentage>',
325325
initialValue: '0px',
326326
});
327327
expect(inferSyntaxFromValue('2rem')).toEqual({
328-
syntax: '<length>',
328+
syntax: '<length-percentage>',
329329
initialValue: '0px',
330330
});
331331
expect(inferSyntaxFromValue('1em')).toEqual({
332-
syntax: '<length>',
332+
syntax: '<length-percentage>',
333333
initialValue: '0px',
334334
});
335335
expect(inferSyntaxFromValue('100vw')).toEqual({
336-
syntax: '<length>',
336+
syntax: '<length-percentage>',
337337
initialValue: '0px',
338338
});
339339
});
340340

341-
it('should infer <percentage> from percent values', () => {
341+
it('should infer <length-percentage> from percent values', () => {
342342
expect(inferSyntaxFromValue('50%')).toEqual({
343-
syntax: '<percentage>',
344-
initialValue: '0%',
343+
syntax: '<length-percentage>',
344+
initialValue: '0px',
345345
});
346346
});
347347

src/properties/property-type-resolver.test.ts

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,14 @@ describe('PropertyTypeResolver', () => {
3131
});
3232
});
3333

34-
it('should register a length property', () => {
34+
it('should register a length-percentage property from length value', () => {
3535
resolver.scanDeclarations(
3636
'--gap: 10px',
3737
isPropertyDefined,
3838
registerProperty,
3939
);
4040
expect(registered.get('--gap')).toEqual({
41-
syntax: '<length>',
41+
syntax: '<length-percentage>',
4242
initialValue: '0px',
4343
});
4444
});
@@ -67,15 +67,15 @@ describe('PropertyTypeResolver', () => {
6767
});
6868
});
6969

70-
it('should register a percentage property', () => {
70+
it('should register a length-percentage property from percentage value', () => {
7171
resolver.scanDeclarations(
7272
'--progress: 50%',
7373
isPropertyDefined,
7474
registerProperty,
7575
);
7676
expect(registered.get('--progress')).toEqual({
77-
syntax: '<percentage>',
78-
initialValue: '0%',
77+
syntax: '<length-percentage>',
78+
initialValue: '0px',
7979
});
8080
});
8181

@@ -118,11 +118,11 @@ describe('PropertyTypeResolver', () => {
118118
registerProperty,
119119
);
120120
expect(registered.get('--b')).toEqual({
121-
syntax: '<length>',
121+
syntax: '<length-percentage>',
122122
initialValue: '0px',
123123
});
124124
expect(registered.get('--a')).toEqual({
125-
syntax: '<length>',
125+
syntax: '<length-percentage>',
126126
initialValue: '0px',
127127
});
128128
});
@@ -225,4 +225,54 @@ describe('PropertyTypeResolver', () => {
225225
expect(registered.size).toBe(0);
226226
});
227227
});
228+
229+
describe('line-height name-based inference', () => {
230+
it('should register --line-height with var() as <number> | <length-percentage>', () => {
231+
resolver.scanDeclarations(
232+
'--line-height: var(--lh)',
233+
isPropertyDefined,
234+
registerProperty,
235+
);
236+
expect(registered.get('--line-height')).toEqual({
237+
syntax: '<number> | <length-percentage>',
238+
initialValue: '0',
239+
});
240+
});
241+
242+
it('should register --*-line-height with var() as <number> | <length-percentage>', () => {
243+
resolver.scanDeclarations(
244+
'--heading-line-height: var(--lh)',
245+
isPropertyDefined,
246+
registerProperty,
247+
);
248+
expect(registered.get('--heading-line-height')).toEqual({
249+
syntax: '<number> | <length-percentage>',
250+
initialValue: '0',
251+
});
252+
});
253+
254+
it('should use name-based type even when value is a bare number', () => {
255+
resolver.scanDeclarations(
256+
'--line-height: 1.5',
257+
isPropertyDefined,
258+
registerProperty,
259+
);
260+
expect(registered.get('--line-height')).toEqual({
261+
syntax: '<number> | <length-percentage>',
262+
initialValue: '0',
263+
});
264+
});
265+
266+
it('should use name-based type even when value is a length', () => {
267+
resolver.scanDeclarations(
268+
'--body-line-height: 24px',
269+
isPropertyDefined,
270+
registerProperty,
271+
);
272+
expect(registered.get('--body-line-height')).toEqual({
273+
syntax: '<number> | <length-percentage>',
274+
initialValue: '0',
275+
});
276+
});
277+
});
228278
});

src/properties/property-type-resolver.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ export class PropertyTypeResolver {
5050
continue;
5151
}
5252

53+
// Name-based: --*-line-height accepts numbers, lengths, and percentages
54+
if (propName.endsWith('-line-height')) {
55+
registerProperty(propName, '<number> | <length-percentage>', '0');
56+
continue;
57+
}
58+
5359
// Single var() reference → record dependency for deferred resolution
5460
const varMatch = SINGLE_VAR_REF.exec(value);
5561
if (varMatch) {

src/ssr/ssr.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,7 @@ describe('collectAutoInferredProperties', () => {
562562
expect(css).toContain('initial-value: 0deg');
563563
});
564564

565-
it('infers <length> from pixel values', () => {
565+
it('infers <length-percentage> from pixel values', () => {
566566
const collector = new ServerStyleCollector();
567567

568568
collectAutoInferredProperties(
@@ -572,7 +572,7 @@ describe('collectAutoInferredProperties', () => {
572572

573573
const css = collector.getCSS();
574574
expect(css).toContain('@property --offset');
575-
expect(css).toContain('"<length>"');
575+
expect(css).toContain('"<length-percentage>"');
576576
expect(css).toContain('initial-value: 0px');
577577
});
578578

src/styles.test.ts

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -260,34 +260,29 @@ describe('Tasty style tests', () => {
260260
preset: 't3',
261261
}),
262262
).toEqual({
263-
'--font-size': 'var(--t3-font-size, var(--default-font-size, inherit))',
264-
'--font-style':
265-
'var(--t3-font-style, var(--default-font-style, inherit))',
266-
'--font-weight':
267-
'var(--t3-font-weight, var(--default-font-weight, inherit))',
263+
'--font-size': 'var(--t3-font-size, var(--default-font-size))',
264+
'--font-style': 'var(--t3-font-style, var(--default-font-style))',
265+
'--font-weight': 'var(--t3-font-weight, var(--default-font-weight))',
268266
'--letter-spacing':
269-
'var(--t3-letter-spacing, var(--default-letter-spacing, inherit))',
270-
'--line-height':
271-
'var(--t3-line-height, var(--default-line-height, inherit))',
267+
'var(--t3-letter-spacing, var(--default-letter-spacing))',
268+
'--line-height': 'var(--t3-line-height, var(--default-line-height))',
272269
'--bold-font-weight':
273-
'var(--t3-bold-font-weight, var(--default-bold-font-weight, inherit))',
270+
'var(--t3-bold-font-weight, var(--default-bold-font-weight))',
274271
'--font-family':
275272
'var(--t3-font-family, var(--default-font-family, var(--font, NonexistentFontName))), var(--font, sans-serif)',
276-
'--icon-size': 'var(--t3-icon-size, var(--default-icon-size, inherit))',
273+
'--icon-size': 'var(--t3-icon-size, var(--default-icon-size))',
277274
'--text-transform':
278-
'var(--t3-text-transform, var(--default-text-transform, inherit))',
279-
'font-size': 'var(--t3-font-size, var(--default-font-size, inherit))',
280-
'font-style': 'var(--t3-font-style, var(--default-font-style, inherit))',
281-
'font-weight':
282-
'var(--t3-font-weight, var(--default-font-weight, inherit))',
275+
'var(--t3-text-transform, var(--default-text-transform))',
276+
'font-size': 'var(--t3-font-size, var(--default-font-size))',
277+
'font-style': 'var(--t3-font-style, var(--default-font-style))',
278+
'font-weight': 'var(--t3-font-weight, var(--default-font-weight))',
283279
'letter-spacing':
284-
'var(--t3-letter-spacing, var(--default-letter-spacing, inherit))',
285-
'line-height':
286-
'var(--t3-line-height, var(--default-line-height, inherit))',
280+
'var(--t3-letter-spacing, var(--default-letter-spacing))',
281+
'line-height': 'var(--t3-line-height, var(--default-line-height))',
287282
'font-family':
288283
'var(--t3-font-family, var(--default-font-family, var(--font, NonexistentFontName))), var(--font, sans-serif)',
289284
'text-transform':
290-
'var(--t3-text-transform, var(--default-text-transform, inherit))',
285+
'var(--t3-text-transform, var(--default-text-transform))',
291286
});
292287
});
293288

src/styles/preset.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,8 @@ function setCSSValue(
3030
return 'inherit';
3131
}
3232

33-
const defaultValue = `var(--default-${styleName}, ${
34-
styleName === 'font-family'
35-
? 'var(--font, NonexistentFontName)'
36-
: 'inherit'
33+
const defaultValue = `var(--default-${styleName}${
34+
styleName === 'font-family' ? ', var(--font, NonexistentFontName)' : ''
3735
})`;
3836
const fontSuffix =
3937
styleName === 'font-family' ? ', var(--font, sans-serif)' : '';

0 commit comments

Comments
 (0)