Skip to content

Commit a1aa0a5

Browse files
committed
Handle theme method spreads in the sx prop
1 parent 3a32e8d commit a1aa0a5

File tree

11 files changed

+68
-39
lines changed

11 files changed

+68
-39
lines changed

packages/pigment-react/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ const Heading = styled('h1')({
217217
});
218218
```
219219

220-
Zero-runtime will replace the callback with a CSS variable and inject the value through inline style. This makes it possible to create a static CSS file while still allowing dynamic styles.
220+
Pigment CSS will replace the callback with a CSS variable and inject the value through inline style. This makes it possible to create a static CSS file while still allowing dynamic styles.
221221

222222
```css
223223
.Heading_class_akjsdfb {
@@ -322,7 +322,7 @@ const Heading = styled('h1')(({ theme }) => ({
322322

323323
#### CSS variables support
324324

325-
Zero-runtime can generate CSS variables from the theme values when you wrap your theme with `extendTheme` utility. For example, in a `next.config.js` file:
325+
Pigment CSS can generate CSS variables from the theme values when you wrap your theme with `extendTheme` utility. For example, in a `next.config.js` file:
326326

327327
```js
328328
const { withPigment, extendTheme } = require('@pigment-css/nextjs-plugin');

packages/pigment-react/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,3 @@ export { default as keyframes } from './keyframes';
44
export { generateAtomics, atomics } from './generateAtomics';
55
export { default as css } from './css';
66
export { default as createUseThemeProps } from './createUseThemeProps';
7-
export { clsx } from 'clsx';

packages/pigment-react/src/utils/pre-linaria-plugin.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { addNamed } from '@babel/helper-module-imports';
22
import { declare } from '@babel/helper-plugin-utils';
33
import { NodePath } from '@babel/core';
44
import * as Types from '@babel/types';
5-
import { sxPropConvertor } from './sxPropConverter';
5+
import { sxPropConverter } from './sxPropConverter';
66

77
function replaceNodePath(
88
expressionPath: NodePath<Types.Expression>,
@@ -19,7 +19,7 @@ function replaceNodePath(
1919
);
2020
};
2121

22-
sxPropConvertor(expressionPath, wrapWithSxCall);
22+
sxPropConverter(expressionPath, wrapWithSxCall);
2323
}
2424

2525
export const babelPlugin = declare<{ propName?: string; importName?: string }>(

packages/pigment-react/src/utils/sxObjectExtractor.ts

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ function validateObjectKey(
2323
return;
2424
}
2525
if (!parentCall) {
26-
throw keyPath.buildCodeFrameError('Expressions in css object keys are not supported.');
26+
throw keyPath.buildCodeFrameError(
27+
`${process.env.PACKAGE_NAME}: Expressions in css object keys are not supported.`,
28+
);
2729
}
2830
if (
2931
!identifiers.every((item) => {
@@ -41,7 +43,7 @@ function validateObjectKey(
4143
})
4244
) {
4345
throw keyPath.buildCodeFrameError(
44-
'Variables in css object keys should only use the passed theme(s) object or variables that are defined in the root scope.',
46+
`${process.env.PACKAGE_NAME}: Variables in css object keys should only use the passed theme(s) object or variables that are defined in the root scope.`,
4547
);
4648
}
4749
}
@@ -59,14 +61,14 @@ function traverseObjectExpression(
5961
const value = property.get('value');
6062
if (!value.isExpression()) {
6163
throw value.buildCodeFrameError(
62-
'This value is not supported. It can only be static values or local variables.',
64+
`${process.env.PACKAGE_NAME}: This value is not supported. It can only be static values or local variables.`,
6365
);
6466
}
6567
if (value.isObjectExpression()) {
6668
traverseObjectExpression(value, parentCall);
6769
} else if (value.isArrowFunctionExpression()) {
6870
throw value.buildCodeFrameError(
69-
'Arrow functions are not supported as values of sx object.',
71+
`${process.env.PACKAGE_NAME}: Arrow functions are not supported as values of sx object.`,
7072
);
7173
} else if (!value.isLiteral() && !isStaticObjectOrArrayExpression(value)) {
7274
const identifiers = findIdentifiers([value], 'reference');
@@ -86,7 +88,7 @@ function traverseObjectExpression(
8688
localIdentifiers.push(id);
8789
} else {
8890
throw id.buildCodeFrameError(
89-
'Consider moving this variable to the root scope if it has all static values.',
91+
`${process.env.PACKAGE_NAME}: Consider moving this variable to the root scope if it has all static values.`,
9092
);
9193
}
9294
});
@@ -103,20 +105,23 @@ function traverseObjectExpression(
103105
if (
104106
!identifiers.every((id) => {
105107
const binding = property.scope.getBinding(id.node.name);
106-
if (!binding || binding.scope !== rootScope) {
107-
return false;
108-
}
109-
return true;
108+
// the indentifier definition should either be in the root scope or in the same scope
109+
// as the object property, ie, ({theme}) => ({...theme.applyStyles()})
110+
return binding && (binding.scope === rootScope || binding.scope === property.scope);
110111
})
111112
) {
112113
throw property.buildCodeFrameError(
113-
'You can only use variables that are defined in the root scope of the file.',
114+
`${process.env.PACKAGE_NAME}: You can only use variables in the spread that are defined in the root scope of the file.`,
114115
);
115116
}
116117
} else if (property.isObjectMethod()) {
117-
throw property.buildCodeFrameError('sx prop object does not support ObjectMethods.');
118+
throw property.buildCodeFrameError(
119+
`${process.env.PACKAGE_NAME}: sx prop object does not support ObjectMethods.`,
120+
);
118121
} else {
119-
throw property.buildCodeFrameError('Unknown property in object.');
122+
throw property.buildCodeFrameError(
123+
`${process.env.PACKAGE_NAME}: Unknown property in object.`,
124+
);
120125
}
121126
});
122127
}
@@ -128,7 +133,7 @@ export function sxObjectExtractor(nodePath: NodePath<ObjectExpression | ArrowFun
128133
const body = nodePath.get('body');
129134
if (!body.isObjectExpression()) {
130135
throw body.buildCodeFrameError(
131-
"sx prop only supports arrow functions that directly return an object, e.g. () => ({color: 'red'}). You can accept theme object in the params if required.",
136+
`${process.env.PACKAGE_NAME}: sx prop only supports arrow functions directly returning an object, e.g. () => ({color: 'red'}). You can accept theme object in the params if required.`,
132137
);
133138
}
134139
traverseObjectExpression(body, nodePath);

packages/pigment-react/src/utils/sxPropConverter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ function isAllowedExpression(
88
return node.isObjectExpression() || node.isArrowFunctionExpression();
99
}
1010

11-
export function sxPropConvertor(
11+
export function sxPropConverter(
1212
node: NodePath<Expression>,
1313
wrapWithSxCall: (expPath: NodePath<Expression>) => void,
1414
) {

packages/pigment-react/tests/fixtures/styled.input.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ const rotateKeyframe = keyframes({
1010
});
1111

1212
const Component = styled.div(({ theme }) => ({
13-
color: theme.palette.primary.main,
13+
color: (theme.vars ?? theme).palette.primary.main,
1414
animation: `${rotateKeyframe} 2s ease-out 0s infinite`,
1515
}));
1616

1717
const cls1 = css`
18-
color: ${({ theme }) => theme.palette.primary.main};
19-
font-size: ${({ theme }) => theme.size.font.h1};
18+
color: ${({ theme }) => (theme.vars ?? theme).palette.primary.main};
19+
font-size: ${({ theme }) => (theme.vars ?? theme).size.font.h1};
2020
`;
2121

2222
export const SliderRail = styled('span', {
@@ -28,11 +28,11 @@ export const SliderRail = styled('span', {
2828
border-radius: inherit;
2929
background-color: currentColor;
3030
opacity: 0.38;
31-
font-size: ${({ theme }) => theme.size.font.h1};
31+
font-size: ${({ theme }) => (theme.vars ?? theme).size.font.h1};
3232
`;
3333

3434
const SliderRail2 = styled.span`
3535
display: block;
3636
opacity: 0.38;
37-
font-size: ${({ theme }) => theme.size.font.h1};
37+
font-size: ${({ theme }) => (theme.vars ?? theme).size.font.h1};
3838
`;
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
@keyframes r1ub6j9g{from{transform:rotate(360deg);}to{transform:rotate(0deg);}}
2-
.c1y26wbb{color:red;animation:r1ub6j9g 2s ease-out 0s infinite;}
3-
.ct00dwm{color:red;font-size:3rem;}
4-
.soujkwr{display:block;position:absolute;border-radius:inherit;background-color:currentColor;opacity:0.38;font-size:3rem;}
2+
.c1y26wbb{color:var(--mui-palette-primary-main);animation:r1ub6j9g 2s ease-out 0s infinite;}
3+
.ct00dwm{color:var(--mui-palette-primary-main);font-size:var(--mui-size-font-h1);}
4+
.soujkwr{display:block;position:absolute;border-radius:inherit;background-color:currentColor;opacity:0.38;font-size:var(--mui-size-font-h1);}
55
.soujkwr-1{font-size:3rem;}
6-
.s14dtw5g{display:block;opacity:0.38;font-size:3rem;}
6+
.s14dtw5g{display:block;opacity:0.38;font-size:var(--mui-size-font-h1);}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { SliderRail } from './styled.input';
2+
3+
function App2(props) {
4+
return (
5+
<SliderRail
6+
sx={({ theme }) => ({
7+
mb: 1,
8+
...theme.applyStyles('dark', {
9+
color: 'white',
10+
}),
11+
})}
12+
/>
13+
);
14+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.soujkwr.sqyvpfz{margin-bottom:8px;}@media (prefers-color-scheme: dark){.soujkwr.sqyvpfz{color:white;}}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { SliderRail } from './styled.input';
2+
function App2(props) {
3+
return <SliderRail sx={"sqyvpfz"} />;
4+
}

packages/pigment-react/tests/pigment.test.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,40 @@ import { expect } from 'chai';
44
import { asyncResolveFallback } from '@wyw-in-js/shared';
55
import { transformAsync } from '@babel/core';
66
import { TransformCacheCollection, transform, createFileReporter } from '@wyw-in-js/transform';
7-
import { preprocessor } from '@pigment-css/react/utils';
7+
import { preprocessor, extendTheme } from '@pigment-css/react/utils';
88
import sxTransformPlugin from '../exports/sx-plugin';
99

1010
const files = fs
1111
.readdirSync(path.join(__dirname, 'fixtures'))
1212
.filter((file) => file.endsWith('.input.js'));
1313

14-
const theme = {
15-
palette: {
16-
primary: {
17-
main: 'red',
18-
},
19-
},
20-
size: {
21-
font: {
22-
h1: '3rem',
14+
const theme = extendTheme({
15+
colorSchemes: {
16+
light: {
17+
palette: {
18+
primary: {
19+
main: 'red',
20+
},
21+
},
22+
size: {
23+
font: {
24+
h1: '3rem',
25+
},
26+
},
2327
},
2428
},
2529
components: {
2630
MuiSlider: {
31+
defaultProps: {},
2732
styleOverrides: {
2833
rail: {
2934
fontSize: '3rem',
3035
},
3136
},
3237
},
3338
},
34-
};
39+
cssVarPrefix: 'mui',
40+
});
3541

3642
async function transformWithSx(code: string, filename: string) {
3743
const babelResult = await transformAsync(code, {

0 commit comments

Comments
 (0)