Skip to content

Commit

Permalink
[core] Add support for sx replacement in transformed jsx calls
Browse files Browse the repository at this point in the history
  • Loading branch information
brijeshb42 committed Apr 19, 2024
1 parent de70dee commit 9b9f418
Show file tree
Hide file tree
Showing 10 changed files with 97 additions and 16 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@
"@types/lodash": "^4.17.0",
"@types/mocha": "^10.0.6",
"@types/node": "^18.19.30",
"@types/prettier": "^3.0.0",
"@types/react": "^18.2.74",
"@types/yargs": "^17.0.32",
"@typescript-eslint/eslint-plugin": "^7.5.0",
Expand Down
34 changes: 32 additions & 2 deletions packages/pigment-css-react/src/utils/sx-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function convertJsxMemberExpressionToMemberExpression(
);
}

function wrapWithSxComponent(
function wrapWithJsxElement(
t: typeof Types,
tagNamePath: NodePath<Types.JSXIdentifier | Types.JSXMemberExpression | Types.JSXNamespacedName>,
sxComponentName: string,
Expand Down Expand Up @@ -71,6 +71,34 @@ function wrapWithSxComponent(
jsxElement.replaceWith(newElement);
}

function wrapWithJsxCall(
t: typeof Types,
tagNamePath: NodePath<Types.Identifier | Types.MemberExpression>,
sxComponentName: string,
) {
const sxComponent = addNamed(
tagNamePath,
sxComponentName,
`${process.env.PACKAGE_NAME}/private-runtime`,
);
const jsxCall = tagNamePath.findParent((p) => p.isCallExpression());
if (!jsxCall?.isCallExpression()) {
return;
}
const originalTag = tagNamePath.node;
const callArgs = jsxCall.get('arguments');
callArgs[0].replaceWith(sxComponent);
const props = callArgs[1];
if (props.isObjectExpression()) {
const properties = props.get('properties');
const newProps = t.objectExpression([
t.objectProperty(t.identifier('sxComponent'), originalTag),
...properties.map((p) => p.node),
]);
props.replaceWith(newProps);
}
}

function replaceNodePath(
expressionPath: NodePath<Types.Expression>,
namePath: NodePath<Types.JSXIdentifier | Types.Identifier>,
Expand Down Expand Up @@ -101,7 +129,9 @@ function replaceNodePath(

if (wasSxTransformed) {
if (tagNamePath.isJSXIdentifier() || tagNamePath.isJSXMemberExpression()) {
wrapWithSxComponent(t, tagNamePath, sxComponentName);
wrapWithJsxElement(t, tagNamePath, sxComponentName);
} else if (tagNamePath.isIdentifier() || tagNamePath.isMemberExpression()) {
wrapWithJsxCall(t, tagNamePath, sxComponentName);
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions packages/pigment-css-react/tests/Box/box.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,13 @@ describe('Pigment CSS - Box', () => {
expect(output.js).to.equal(fixture.js);
expect(output.css).to.equal(fixture.css);
});

it('should transform and render sx prop for jsx calls', async () => {
const { output, fixture } = await runTransformation(
path.join(__dirname, 'fixtures/box-jsx.input.js'),
);

expect(output.js).to.equal(fixture.js);
expect(output.css).to.equal(fixture.css);
});
});
19 changes: 19 additions & 0 deletions packages/pigment-css-react/tests/Box/fixtures/box-jsx.input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Box from '@pigment-css/react/Box';
import { jsx as _jsx } from 'react/jsx-runtime';

export function App(props) {
return /*#__PURE__*/ _jsx(Box, {
as: 'ul',
'aria-label': props.label,
sx: {
margin: 0,
marginBlock: '1rem',
padding: 0,
paddingLeft: '1.5rem',
display: 'flex',
flexDirection: 'column',
gap: '0.5rem',
},
children: 'Hello Box',
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.sd5jss7 {
margin: 0;
margin-block: 1rem;
padding: 0;
padding-left: 1.5rem;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
12 changes: 12 additions & 0 deletions packages/pigment-css-react/tests/Box/fixtures/box-jsx.output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ForwardSx as _ForwardSx } from '@pigment-css/react/private-runtime';
import Box from '@pigment-css/react/Box';
import { jsx as _jsx } from 'react/jsx-runtime';
export function App(props) {
return /*#__PURE__*/ _jsx(_ForwardSx, {
sxComponent: Box,
as: 'ul',
'aria-label': props.label,
sx: 'sd5jss7',
children: 'Hello Box',
});
}
4 changes: 3 additions & 1 deletion packages/pigment-css-react/tests/Box/fixtures/box.input.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import Box from '@pigment-css/react/Box';

export function App() {
export function App(props) {
return (
<Box
as="ul"
aria-label={props.label}
sx={{
color: props.color,
margin: 0,
marginBlock: '1rem',
padding: 0,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
._c1d15y {
color: var(--_c1d15y-0);
margin: 0;
margin-block: 1rem;
padding: 0;
Expand Down
14 changes: 12 additions & 2 deletions packages/pigment-css-react/tests/Box/fixtures/box.output.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
import { sx as _sx2 } from '@pigment-css/react';
import { ForwardSx as _ForwardSx } from '@pigment-css/react/private-runtime';
import Box from '@pigment-css/react/Box';
export function App() {
export function App(props) {
return (
<_ForwardSx sxComponent={Box} as="ul" sx={'_c1d15y'}>
<_ForwardSx
sxComponent={Box}
as="ul"
aria-label={props.label}
sx={{
className: '_c1d15y',
vars: {
'_c1d15y-0': [props.color, false],
},
}}
>
Hello Box
</_ForwardSx>
);
Expand Down
10 changes: 0 additions & 10 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 9b9f418

Please sign in to comment.