Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions packages/core/ui/styling/length-rem.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { describe, it, expect, afterEach } from 'vitest';

import { Length, FixedLength, PercentLength } from './length-shared';
import { Label } from '../label';

describe('rem lengths', () => {
afterEach(() => Length.setRootFontSize(16));

it('are multiples of the root font size, 16 by default', () => {
expect(Length.getRootFontSize()).toBe(16);
expect(Length.parse('1rem')).toBe(16);
expect(FixedLength.parse(' 0.5rem ')).toBe(8);
expect(PercentLength.parse('1.5rem')).toBe(24);
expect(PercentLength.parse('-1rem')).toBe(-16);
});

it('follow a root font size set before parsing', () => {
Length.setRootFontSize(10);

expect(Length.parse('2rem')).toBe(20);
});

it('ignore an invalid root font size', () => {
Length.setRootFontSize(0);
Length.setRootFontSize(NaN);

expect(Length.getRootFontSize()).toBe(16);
});

it('reject an invalid rem value', () => {
expect(() => Length.parse('remrem')).toThrow('Invalid value');
});

it('leave other units as they were', () => {
expect(Length.parse('10')).toBe(10);
expect(Length.parse('10px')).toEqual({ unit: 'px', value: 10 });
expect(PercentLength.parse('50%')).toEqual({ unit: '%', value: 0.5 });
});

it('apply to css lengths and font sizes', () => {
const label = new Label();
label.style['css:margin-top'] = '0.5rem';
label.style['css:font-size'] = '1.25rem';

expect(label.style.marginTop).toBe(8);
expect(label.style.fontSize).toBe(20);
});

it('apply in the font shorthand', () => {
const label = new Label();
label.style['css:font'] = 'italic 2rem serif';

expect(label.style.fontSize).toBe(32);
});
});
28 changes: 28 additions & 0 deletions packages/core/ui/styling/length-shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,21 @@ import { CoreTypes } from '../../core-types';
import { layout } from '../../utils/layout-helper';
import { isCssWideKeyword } from '../core/properties/property-shared';

let rootFontSize = 16;

function parseRem(value: string): CoreTypes.dip | undefined {
if (!value.endsWith('rem')) {
return undefined;
}

const rem = parseFloat(value.substring(0, value.length - 3));
if (isNaN(rem) || !isFinite(rem)) {
throw new Error(`Invalid value: ${value}`);
}

return rem * rootFontSize;
}

function equalsCommon(a: CoreTypes.LengthType, b: CoreTypes.LengthType): boolean;
function equalsCommon(a: CoreTypes.PercentLengthType, b: CoreTypes.PercentLengthType): boolean;
function equalsCommon(a: CoreTypes.PercentLengthType, b: CoreTypes.PercentLengthType): boolean {
Expand Down Expand Up @@ -101,6 +116,8 @@ export namespace PercentLength {
}

return { unit: '%', value };
} else if (stringValue.endsWith('rem')) {
return parseRem(stringValue);
} else if (stringValue.indexOf('px') !== -1) {
stringValue = stringValue.replace('px', '').trim();
const value: CoreTypes.px = parseFloat(stringValue);
Expand Down Expand Up @@ -143,6 +160,9 @@ export namespace FixedLength {
export function parse(fromValue: string | CoreTypes.FixedLengthType): CoreTypes.FixedLengthType {
if (typeof fromValue === 'string') {
let stringValue = fromValue.trim();
if (stringValue.endsWith('rem')) {
return parseRem(stringValue);
}
if (stringValue.indexOf('px') !== -1) {
stringValue = stringValue.replace('px', '').trim();
const value: CoreTypes.px = parseFloat(stringValue);
Expand Down Expand Up @@ -196,4 +216,12 @@ export namespace Length {
export const convertToString: {
(length: CoreTypes.LengthType): string;
} = convertToStringCommon;
export function getRootFontSize(): number {
return rootFontSize;
}
export function setRootFontSize(size: number): void {
if (size > 0 && isFinite(size)) {
rootFontSize = size;
}
}
}
8 changes: 6 additions & 2 deletions packages/core/ui/styling/style-properties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1195,6 +1195,10 @@ export const fontScaleInternalProperty = new InheritedCssProperty<Style, number>
});
fontScaleInternalProperty.register(Style);

function parseFontSize(value: string): number {
return typeof value === 'string' && value.trim().endsWith('rem') ? <number>Length.parse(value) : parseFloat(value);
}

export const fontSizeProperty = new InheritedCssProperty<Style, number>({
name: 'fontSize',
cssName: 'font-size',
Expand All @@ -1209,7 +1213,7 @@ export const fontSizeProperty = new InheritedCssProperty<Style, number>({
target.fontInternal = Font.equals(Font.default, newFont) ? unsetValue : newFont;
}
},
valueConverter: (v) => parseFloat(v),
valueConverter: parseFontSize,
});
fontSizeProperty.register(Style);

Expand Down Expand Up @@ -1261,7 +1265,7 @@ const fontProperty = new ShorthandProperty<Style, string>({
];
} else {
const font = parseFont(value);
const fontSize = parseFloat(font.fontSize);
const fontSize = parseFontSize(font.fontSize);

return [
[fontStyleProperty, font.fontStyle],
Expand Down
Loading