diff --git a/package.json b/package.json index 97dbcea2..ea2e7856 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/packages/pigment-css-react/src/utils/sx-plugin.ts b/packages/pigment-css-react/src/utils/sx-plugin.ts index 4265dcfb..d10e781c 100644 --- a/packages/pigment-css-react/src/utils/sx-plugin.ts +++ b/packages/pigment-css-react/src/utils/sx-plugin.ts @@ -24,7 +24,7 @@ function convertJsxMemberExpressionToMemberExpression( ); } -function wrapWithSxComponent( +function wrapWithJsxElement( t: typeof Types, tagNamePath: NodePath, sxComponentName: string, @@ -71,6 +71,34 @@ function wrapWithSxComponent( jsxElement.replaceWith(newElement); } +function wrapWithJsxCall( + t: typeof Types, + tagNamePath: NodePath, + 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, namePath: NodePath, @@ -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); } } } diff --git a/packages/pigment-css-react/tests/Box/box.test.tsx b/packages/pigment-css-react/tests/Box/box.test.tsx index a5a33298..43b3fa03 100644 --- a/packages/pigment-css-react/tests/Box/box.test.tsx +++ b/packages/pigment-css-react/tests/Box/box.test.tsx @@ -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); + }); }); diff --git a/packages/pigment-css-react/tests/Box/fixtures/box-jsx.input.js b/packages/pigment-css-react/tests/Box/fixtures/box-jsx.input.js new file mode 100644 index 00000000..8d4a759c --- /dev/null +++ b/packages/pigment-css-react/tests/Box/fixtures/box-jsx.input.js @@ -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', + }); +} diff --git a/packages/pigment-css-react/tests/Box/fixtures/box-jsx.output.css b/packages/pigment-css-react/tests/Box/fixtures/box-jsx.output.css new file mode 100644 index 00000000..8a99d69c --- /dev/null +++ b/packages/pigment-css-react/tests/Box/fixtures/box-jsx.output.css @@ -0,0 +1,9 @@ +.sd5jss7 { + margin: 0; + margin-block: 1rem; + padding: 0; + padding-left: 1.5rem; + display: flex; + flex-direction: column; + gap: 0.5rem; +} diff --git a/packages/pigment-css-react/tests/Box/fixtures/box-jsx.output.js b/packages/pigment-css-react/tests/Box/fixtures/box-jsx.output.js new file mode 100644 index 00000000..eb330c06 --- /dev/null +++ b/packages/pigment-css-react/tests/Box/fixtures/box-jsx.output.js @@ -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', + }); +} diff --git a/packages/pigment-css-react/tests/Box/fixtures/box.input.js b/packages/pigment-css-react/tests/Box/fixtures/box.input.js index b8548e76..d57e48a2 100644 --- a/packages/pigment-css-react/tests/Box/fixtures/box.input.js +++ b/packages/pigment-css-react/tests/Box/fixtures/box.input.js @@ -1,10 +1,12 @@ import Box from '@pigment-css/react/Box'; -export function App() { +export function App(props) { return ( + <_ForwardSx + sxComponent={Box} + as="ul" + aria-label={props.label} + sx={{ + className: '_c1d15y', + vars: { + '_c1d15y-0': [props.color, false], + }, + }} + > Hello Box ); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8d1f9eb9..c5d156b9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -136,9 +136,6 @@ importers: '@types/node': specifier: ^18.19.30 version: 18.19.31 - '@types/prettier': - specifier: ^3.0.0 - version: 3.0.0 '@types/react': specifier: ^18.2.74 version: 18.2.75 @@ -4941,13 +4938,6 @@ packages: /@types/parse-json@4.0.2: resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} - /@types/prettier@3.0.0: - resolution: {integrity: sha512-mFMBfMOz8QxhYVbuINtswBp9VL2b4Y0QqYHwqLz3YbgtfAcat2Dl6Y1o4e22S/OVE6Ebl9m7wWiMT2lSbAs1wA==} - deprecated: This is a stub types definition. prettier provides its own type definitions, so you do not need this installed. - dependencies: - prettier: 3.2.5 - dev: true - /@types/promise.allsettled@1.0.6: resolution: {integrity: sha512-wA0UT0HeT2fGHzIFV9kWpYz5mdoyLxKrTgMdZQM++5h6pYAFH73HXcQhefg24nD1yivUFEn5KU+EF4b+CXJ4Wg==}