Skip to content
Open
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
6 changes: 3 additions & 3 deletions apps/examples/src/components/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -654,14 +654,14 @@ const animateSequence = css.keyframes({
});

const themedTokens = css.createTheme(tokens, {
squareColor: 'purple',
'--square-color': 'purple',
textColor: 'purple',
inputColor: 'purple',
inputPlaceholderColor: 'mediumpurple'
});

const themedTokensAlt = css.createTheme(tokens, {
squareColor: 'darkorange',
'--square-color': 'darkorange',
textColor: 'darkorange',
inputColor: 'orangered',
inputPlaceholderColor: 'orange'
Expand All @@ -684,7 +684,7 @@ const styles = css.create({
square: {
height: 100,
width: 100,
backgroundColor: tokens.squareColor
backgroundColor: 'var(--square-color)' // check global vars work too
},
pseudoStates: {
height: 50,
Expand Down
4 changes: 2 additions & 2 deletions apps/examples/src/components/tokens.stylex.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import { css } from 'react-strict-dom';

export const tokens: StyleVars<
$ReadOnly<{
squareColor: string,
'--square-color': string,
textColor: string,
inputColor: string,
inputPlaceholderColor: string
}>
> = css.defineVars({
squareColor: 'red',
'--square-color': 'red', // '--' prefix makes this is a global var
textColor: {
default: 'darkred',
'@media (prefers-color-scheme: dark)': 'lightred'
Expand Down
19 changes: 4 additions & 15 deletions packages/react-strict-dom/src/native/stylex/customProperties.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,16 @@ import { CSSUnparsedValue } from './typed-om/CSSUnparsedValue';
import { CSSVariableReferenceValue } from './typed-om/CSSVariableReferenceValue';
import { warnMsg } from '../../shared/logUtils';

const memoizedValues = new Map<string, string>();

function camelize(s: string): string {
const memoizedValue = memoizedValues.get(s);
if (memoizedValue != null) {
return memoizedValue;
}
const result = s.replace(/-./g, (x) => x.toUpperCase()[1]);
memoizedValues.set(s, result);
return result;
}

function normalizeVariableName(name: string): string {
if (__DEV__) {
if (!name.startsWith('--')) {
throw new Error("Invalid variable name, must begin with '--'");
}
}
// TODO: remove camelize
// https://github.com/facebook/react-strict-dom/pull/73
return camelize(name.substring(2));
// Scoped vars created by defineVars all start with __var__.
// But global vars manually created with '--' prefixed keys don't.
const varName = name.startsWith('--__var__') ? name.substring(2) : name;
return varName;
}

export function stringContainsVariables(input: string): boolean {
Expand Down
15 changes: 11 additions & 4 deletions packages/react-strict-dom/src/native/stylex/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -448,8 +448,12 @@ export const createTheme = (
const result: MutableCustomProperties = { $$theme: 'theme' };
for (const key in baseTokens) {
const varName: string = baseTokens[key];
const normalizedKey = varName.replace(RE_CAPTURE_VAR_NAME, '$1');
result[normalizedKey] = overrides[key];
const match = varName.match(RE_CAPTURE_VAR_NAME);
if (match) {
const x = match[1];
const normalizedKey = x.startsWith('__var__') ? x : `--${x}`;
result[normalizedKey] = overrides[key];
}
}
return result;
};
Expand All @@ -466,8 +470,11 @@ export const defineVars = (tokens: CustomProperties): Tokens => {
const result: Tokens = {};
for (const key in tokens) {
const value = tokens[key];
const customPropName = `${key}__id__${defineVarsCount++}`;
result[key] = `var(--${customPropName})`;
const isGlobalVar = key.startsWith('--');
const customPropName = isGlobalVar
? key
: `__var__${defineVarsCount++}_${key}`;
result[key] = isGlobalVar ? `var(${key})` : `var(--${customPropName})`;
// NOTE: it's generally not a good idea to mutate the default context,
// but defineVars is always called before any component body is evaluated,
// and so it's safe to do so here.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@

exports[`properties: custom property css.createTheme: css.__customProperties 1`] = `
{
"rootColor__id__1": "red",
"rootColor__id__3": "red",
"themeAwareColor__id__2": {
"--pass-through": "purple",
"__var__1_rootColor": "red",
"__var__2_themeAwareColor": {
"@media (prefers-color-scheme: dark)": "green",
"default": "blue",
},
"__var__3_rootColor": "red",
}
`;

exports[`properties: custom property css.createTheme: theme 1`] = `
{
"$$theme": "theme",
"rootColor__id__3": "green",
"__var__3_rootColor": "green",
}
`;

Expand All @@ -27,8 +28,9 @@ exports[`properties: custom property css.defineConsts: constants 1`] = `

exports[`properties: custom property css.defineVars: css.__customProperties 1`] = `
{
"rootColor__id__1": "red",
"themeAwareColor__id__2": {
"--pass-through": "purple",
"__var__1_rootColor": "red",
"__var__2_themeAwareColor": {
"@media (prefers-color-scheme: dark)": "green",
"default": "blue",
},
Expand All @@ -37,8 +39,9 @@ exports[`properties: custom property css.defineVars: css.__customProperties 1`]

exports[`properties: custom property css.defineVars: tokens 1`] = `
{
"rootColor": "var(--rootColor__id__1)",
"themeAwareColor": "var(--themeAwareColor__id__2)",
"--pass-through": "var(--pass-through)",
"rootColor": "var(--__var__1_rootColor)",
"themeAwareColor": "var(--__var__2_themeAwareColor)",
}
`;

Expand Down
105 changes: 52 additions & 53 deletions packages/react-strict-dom/tests/css-test.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -1157,7 +1157,7 @@ describe('properties: custom property', () => {
test('legacy strings', () => {
const options = {
customProperties: {
rootColor: 'red'
'--rootColor': 'red'
}
};
expect(
Expand All @@ -1183,7 +1183,8 @@ describe('properties: custom property', () => {
themeAwareColor: {
default: 'blue',
'@media (prefers-color-scheme: dark)': 'green'
}
},
'--pass-through': 'purple'
});
expect(tokens).toMatchSnapshot('tokens');
expect(css.__customProperties).toMatchSnapshot('css.__customProperties');
Expand All @@ -1193,6 +1194,9 @@ describe('properties: custom property', () => {
expect(
resolveCustomPropertyValue(options, ['color', tokens.themeAwareColor])
).toEqual('blue');
expect(
resolveCustomPropertyValue(options, ['color', 'var(--pass-through)'])
).toEqual('purple');
// dark theme
expect(
resolveCustomPropertyValue({ colorScheme: 'dark' }, [
Expand Down Expand Up @@ -1255,7 +1259,9 @@ describe('properties: custom property', () => {

test('parses a basic var correctly', () => {
const options = {
customProperties: { test: 'red' }
customProperties: {
'--test': 'red'
}
};
expect(
resolveCustomPropertyValue(options, ['color', 'var(--test)'])
Expand All @@ -1264,7 +1270,9 @@ describe('properties: custom property', () => {

test('parses a var with a default value', () => {
const options = {
customProperties: { test: 'red' }
customProperties: {
'--test': 'red'
}
};
expect(
resolveCustomPropertyValue(options, ['color', 'var(--test, blue)'])
Expand All @@ -1274,32 +1282,11 @@ describe('properties: custom property', () => {
).toEqual('blue');
});

// TODO: this transform should not be supported. Custom properties are case sensitive.
test('parses kebab case var to camel case', () => {
const options = {
customProperties: { testVar: 'red' }
};
expect(
resolveCustomPropertyValue(options, ['color', 'var(--test-var)'])
).toEqual('red');
});

// TODO: this transform should not be supported. Custom properties are case sensitive.
test('parses kebab case var with a default value', () => {
const options = {
customProperties: { testVar: 'red' }
};
expect(
resolveCustomPropertyValue(options, ['color', 'var(--test-var, blue)'])
).toEqual('red');
expect(
resolveCustomPropertyValue(options, ['color', 'var(--not-found, blue)'])
).toEqual('blue');
});

test('parses a var with a default value containing spaces', () => {
const options = {
customProperties: { color: 'rgb(0,0,0)' }
customProperties: {
'--color': 'rgb(0,0,0)'
}
};
expect(
resolveCustomPropertyValue(options, [
Expand All @@ -1317,7 +1304,9 @@ describe('properties: custom property', () => {

test('parses a var and falls back to default value containing a var', () => {
const options = {
customProperties: { color: 'red' }
customProperties: {
'--color': 'red'
}
};
expect(
resolveCustomPropertyValue(options, [
Expand All @@ -1330,7 +1319,7 @@ describe('properties: custom property', () => {
test('parses a var and falls back to a default value containing spaces and embedded var', () => {
const options = {
customProperties: {
test: '255'
'--test': '255'
}
};
expect(
Expand All @@ -1343,7 +1332,9 @@ describe('properties: custom property', () => {

test('basic var value lookup works', () => {
const options = {
customProperties: { number: 10 }
customProperties: {
'--number': 10
}
};
expect(
resolveCustomPropertyValue(options, ['borderWidth', 'var(--number)'])
Expand All @@ -1352,7 +1343,9 @@ describe('properties: custom property', () => {

test('var value lookup with pixel prop conversion', () => {
const options = {
customProperties: { pxNumber: '10px' }
customProperties: {
'--pxNumber': '10px'
}
};
expect(
resolveCustomPropertyValue(options, ['borderWidth', 'var(--pxNumber)'])
Expand All @@ -1361,7 +1354,9 @@ describe('properties: custom property', () => {

test('var value lookup with em prop conversion', () => {
const options = {
customProperties: { emNumber: '10em' }
customProperties: {
'--emNumber': '10em'
}
};
expect(
resolveCustomPropertyValue(options, ['borderWidth', 'var(--emNumber)'])
Expand All @@ -1371,9 +1366,9 @@ describe('properties: custom property', () => {
test('var value lookup with reference to another var', () => {
const options = {
customProperties: {
number: 10,
refToNumber: 'var(--number)',
refToRefToNumber: 'var(--refToNumber)'
'--number': 10,
'--refToNumber': 'var(--number)',
'--refToRefToNumber': 'var(--refToNumber)'
}
};
expect(
Expand All @@ -1389,7 +1384,9 @@ describe('properties: custom property', () => {

test('var with hover styles', () => {
const options = {
customProperties: { test: '#333' },
customProperties: {
'--test': '#333'
},
hover: true
};
const { underTest } = css.create({
Expand All @@ -1413,7 +1410,9 @@ describe('properties: custom property', () => {

test('rgb(a) function with args applied through a single var', () => {
const options = {
customProperties: { example: '24, 48, 96' }
customProperties: {
'--example': '24, 48, 96'
}
};
expect(
resolveCustomPropertyValue(options, ['color', 'rgb(var(--example))'])
Expand All @@ -1429,11 +1428,11 @@ describe('properties: custom property', () => {
test('rgba function with args applied through multiple (& nested) vars', () => {
const options = {
customProperties: {
red: 255,
green: 96,
blue: 16,
rgb: 'var(--red), var(--green), var(--blue)',
alpha: 0.42
'--red': 255,
'--green': 96,
'--blue': 16,
'--rgb': 'var(--red), var(--green), var(--blue)',
'--alpha': 0.42
}
};
expect(
Expand All @@ -1447,11 +1446,11 @@ describe('properties: custom property', () => {
test('textShadow with nested/multiple vars', () => {
const options = {
customProperties: {
height: '20px',
width: '10px',
size: 'var(--width) var(--height)',
radius: '30px',
red: 'red'
'--height': '20px',
'--width': '10px',
'--size': 'var(--width) var(--height)',
'--radius': '30px',
'--red': 'red'
}
};
const styles = css.create({
Expand All @@ -1474,10 +1473,10 @@ describe('properties: custom property', () => {
test('transform with nested/multiple vars', () => {
const options = {
customProperties: {
distance: 20,
angle: '45deg',
translateX: 'translateX(var(--distance))',
rotateX: 'rotateX(var(--angle))'
'--distance': 20,
'--angle': '45deg',
'--translateX': 'translateX(var(--distance))',
'--rotateX': 'rotateX(var(--angle))'
}
};
const styles = css.create({
Expand All @@ -1495,7 +1494,7 @@ describe('properties: custom property', () => {
test('css variable declaration inside a media query', () => {
const options = {
customProperties: {
example: '42px'
'--example': '42px'
},
viewportWidth: 450
};
Expand Down
2 changes: 1 addition & 1 deletion packages/react-strict-dom/tests/html-test.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ describe('<html.*>', () => {
test('legacy: ThemeProvider', () => {
const { ThemeProvider } = contexts;
const customProperties = {
rootColor: 'red'
'--rootColor': 'red'
};
const styles = css.create({
root: {
Expand Down