Skip to content

Commit

Permalink
Handle theme method spreads in the sx prop
Browse files Browse the repository at this point in the history
  • Loading branch information
brijeshb42 committed Mar 8, 2024
1 parent 8f3c398 commit 66f8d80
Show file tree
Hide file tree
Showing 18 changed files with 247 additions and 148 deletions.
1 change: 0 additions & 1 deletion packages/pigment-react/src/index.ts
Expand Up @@ -4,4 +4,3 @@ export { default as keyframes } from './keyframes';
export { generateAtomics, atomics } from './generateAtomics';
export { default as css } from './css';
export { default as createUseThemeProps } from './createUseThemeProps';
export { clsx } from 'clsx';
4 changes: 2 additions & 2 deletions packages/pigment-react/src/utils/pre-linaria-plugin.ts
Expand Up @@ -2,7 +2,7 @@ import { addNamed } from '@babel/helper-module-imports';
import { declare } from '@babel/helper-plugin-utils';
import { NodePath } from '@babel/core';
import * as Types from '@babel/types';
import { sxPropConvertor } from './sxPropConverter';
import { sxPropConverter } from './sxPropConverter';

function replaceNodePath(
expressionPath: NodePath<Types.Expression>,
Expand All @@ -19,7 +19,7 @@ function replaceNodePath(
);
};

sxPropConvertor(expressionPath, wrapWithSxCall);
sxPropConverter(expressionPath, wrapWithSxCall);
}

export const babelPlugin = declare<{ propName?: string; importName?: string }>(
Expand Down
31 changes: 18 additions & 13 deletions packages/pigment-react/src/utils/sxObjectExtractor.ts
Expand Up @@ -23,7 +23,9 @@ function validateObjectKey(
return;
}
if (!parentCall) {
throw keyPath.buildCodeFrameError('Expressions in css object keys are not supported.');
throw keyPath.buildCodeFrameError(
`${process.env.PACKAGE_NAME}: Expressions in css object keys are not supported.`,
);
}
if (
!identifiers.every((item) => {
Expand All @@ -41,7 +43,7 @@ function validateObjectKey(
})
) {
throw keyPath.buildCodeFrameError(
'Variables in css object keys should only use the passed theme(s) object or variables that are defined in the root scope.',
`${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.`,
);
}
}
Expand All @@ -59,14 +61,14 @@ function traverseObjectExpression(
const value = property.get('value');
if (!value.isExpression()) {
throw value.buildCodeFrameError(
'This value is not supported. It can only be static values or local variables.',
`${process.env.PACKAGE_NAME}: This value is not supported. It can only be static values or local variables.`,
);
}
if (value.isObjectExpression()) {
traverseObjectExpression(value, parentCall);
} else if (value.isArrowFunctionExpression()) {
throw value.buildCodeFrameError(
'Arrow functions are not supported as values of sx object.',
`${process.env.PACKAGE_NAME}: Arrow functions are not supported as values of sx object.`,
);
} else if (!value.isLiteral() && !isStaticObjectOrArrayExpression(value)) {
const identifiers = findIdentifiers([value], 'reference');
Expand All @@ -86,7 +88,7 @@ function traverseObjectExpression(
localIdentifiers.push(id);
} else {
throw id.buildCodeFrameError(
'Consider moving this variable to the root scope if it has all static values.',
`${process.env.PACKAGE_NAME}: Consider moving this variable to the root scope if it has all static values.`,
);
}
});
Expand All @@ -103,20 +105,23 @@ function traverseObjectExpression(
if (
!identifiers.every((id) => {
const binding = property.scope.getBinding(id.node.name);
if (!binding || binding.scope !== rootScope) {
return false;
}
return true;
// the indentifier definition should either be in the root scope or in the same scope
// as the object property, ie, ({theme}) => ({...theme.applyStyles()})
return binding && (binding.scope === rootScope || binding.scope === property.scope);
})
) {
throw property.buildCodeFrameError(
'You can only use variables that are defined in the root scope of the file.',
`${process.env.PACKAGE_NAME}: You can only use variables in the spread that are defined in the root scope of the file.`,
);
}
} else if (property.isObjectMethod()) {
throw property.buildCodeFrameError('sx prop object does not support ObjectMethods.');
throw property.buildCodeFrameError(
`${process.env.PACKAGE_NAME}: sx prop object does not support ObjectMethods.`,
);
} else {
throw property.buildCodeFrameError('Unknown property in object.');
throw property.buildCodeFrameError(
`${process.env.PACKAGE_NAME}: Unknown property in object.`,
);
}
});
}
Expand All @@ -128,7 +133,7 @@ export function sxObjectExtractor(nodePath: NodePath<ObjectExpression | ArrowFun
const body = nodePath.get('body');
if (!body.isObjectExpression()) {
throw body.buildCodeFrameError(
"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.",
`${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.`,
);
}
traverseObjectExpression(body, nodePath);
Expand Down
2 changes: 1 addition & 1 deletion packages/pigment-react/src/utils/sxPropConverter.ts
Expand Up @@ -8,7 +8,7 @@ function isAllowedExpression(
return node.isObjectExpression() || node.isArrowFunctionExpression();
}

export function sxPropConvertor(
export function sxPropConverter(
node: NodePath<Expression>,
wrapWithSxCall: (expPath: NodePath<Expression>) => void,
) {
Expand Down
94 changes: 0 additions & 94 deletions packages/pigment-react/tests/pigment.test.ts

This file was deleted.

6 changes: 3 additions & 3 deletions packages/pigment-react/tests/styled/fixtures/styled.input.js
Expand Up @@ -10,7 +10,7 @@ const rotateKeyframe = keyframes({
});

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

Expand All @@ -23,11 +23,11 @@ export const SliderRail = styled('span', {
border-radius: inherit;
background-color: currentColor;
opacity: 0.38;
font-size: ${({ theme }) => theme.size.font.h1};
font-size: ${({ theme }) => (theme.vars ?? theme).size.font.h1};
`;

const SliderRail2 = styled.span`
display: block;
opacity: 0.38;
font-size: ${({ theme }) => theme.size.font.h1};
font-size: ${({ theme }) => (theme.vars ?? theme).size.font.h1};
`;
Expand Up @@ -11,7 +11,7 @@
animation: r1419f2q 2s ease-out 0s infinite;
}
.s1sjy0ja {
display: none;
display: block;
position: absolute;
border-radius: inherit;
background-color: currentColor;
Expand Down
Expand Up @@ -5,7 +5,7 @@ import _theme from '@pigment-css/react/theme';
const Component = /*#__PURE__*/ _styled('div')({
classes: ['c1vtarpi'],
});
const SliderRail = /*#__PURE__*/ _styled2('span', {
export const SliderRail = /*#__PURE__*/ _styled2('span', {
name: 'MuiSlider',
slot: 'Rail',
})({
Expand Down

This file was deleted.

23 changes: 0 additions & 23 deletions packages/pigment-react/tests/styled/fixtures/sxProps.output.js

This file was deleted.

@@ -1,4 +1,16 @@
import { SliderRail } from './styled.input';
import { styled } from '@pigment-css/react';

export const SliderRail = styled('span', {
name: 'MuiSlider',
slot: 'Rail',
})`
display: block;
position: absolute;
border-radius: inherit;
background-color: currentColor;
opacity: 0.38;
font-size: ${({ theme }) => (theme.vars ?? theme).size.font.h1};
`;

function App() {
return <SliderRail sx={{ color: 'red' }} />;
Expand Down
28 changes: 28 additions & 0 deletions packages/pigment-react/tests/sx/fixtures/sxProps.output.css
@@ -0,0 +1,28 @@
.s4jxdij {
display: block;
position: absolute;
border-radius: inherit;
background-color: currentColor;
opacity: 0.38;
font-size: 3rem;
}
.s4jxdij-1 {
font-size: 3rem;
}
.s4jxdij.s6g18tg {
color: red;
}
.s4jxdij.sqa8j32 {
color: var(--sqa8j32-0);
}
.s4jxdij.s1vuaneo {
background-color: blue;
color: white;
}
.s4jxdij.sihzw1t {
color: var(--sihzw1t-0);
}
.s4jxdij.s1cb6hjd {
margin-bottom: 8px;
text-align: center;
}
43 changes: 43 additions & 0 deletions packages/pigment-react/tests/sx/fixtures/sxProps.output.js
@@ -0,0 +1,43 @@
import { styled as _styled } from '@pigment-css/react';
export const SliderRail = /*#__PURE__*/ _styled('span', {
name: 'MuiSlider',
slot: 'Rail',
})({
classes: ['s4jxdij', 's4jxdij-1'],
});
function App() {
return <SliderRail sx={'s6g18tg'} />;
}
function App2(props) {
return (
<SliderRail
sx={
props.variant === 'secondary'
? {
className: 'sqa8j32',
vars: {
'sqa8j32-0': [props.isRed ? 'red' : 'blue', false],
},
}
: 's1vuaneo'
}
/>
);
}
function App3(props) {
return (
<SliderRail
sx={
props.variant === 'secondary' && {
className: 'sihzw1t',
vars: {
'sihzw1t-0': [props.isRed ? 'red' : 'blue', false],
},
}
}
/>
);
}
function App4(props) {
return <SliderRail sx={'s1cb6hjd'} />;
}

0 comments on commit 66f8d80

Please sign in to comment.