Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pigment-css][react] Fix sx prop transformation on Box #41705

Merged
merged 1 commit into from
Apr 2, 2024
Merged
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
10 changes: 6 additions & 4 deletions apps/pigment-css-next-app/src/app/material-ui/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,25 @@ import Link from 'next/link';
import fs from 'fs/promises';
import path from 'path';
import { css } from '@pigment-css/react';
import Box from '@pigment-css/react/Box';

export default async function MaterialUIPage() {
const rootPaths = await fs.readdir(path.join(process.cwd(), `src/app/material-ui`));
return (
<div>
<h1>Material UI Components</h1>
<nav>
<ul
className={css({
<Box
as="ul"
sx={{
margin: 0,
marginBlock: '1rem',
padding: 0,
paddingLeft: '1.5rem',
display: 'flex',
flexDirection: 'column',
gap: '0.5rem',
})}
}}
>
{rootPaths
.filter((item) => !item.match(/\.(js|tsx)$/))
Expand All @@ -37,7 +39,7 @@ export default async function MaterialUIPage() {
</Link>
</li>
))}
</ul>
</Box>
</nav>
</div>
);
Expand Down
5 changes: 5 additions & 0 deletions apps/pigment-css-vite-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@
"dependsOn": [
"^build"
]
},
"dev": {
"dependsOn": [
"^build"
]
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion apps/pigment-css-vite-app/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ThemeProvider, createTheme } from '@mui/material/styles';
import CircularProgress from '@mui/material/CircularProgress';
import CssBaseline from '@mui/material/CssBaseline';
import { css } from '@pigment-css/react';
import { Box } from '@pigment-css/react/Box';
import Box from '@pigment-css/react/Box';
import { ErrorBoundary } from 'react-error-boundary';
import routes from '~react-pages';
import '@pigment-css/react/styles.css';
Expand Down
20 changes: 11 additions & 9 deletions apps/pigment-css-vite-app/src/pages/material-ui/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { useLocation, matchRoutes, Link } from 'react-router-dom';
import { css } from '@pigment-css/react';
import Box from '@pigment-css/react/Box';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess there will be a question about the import in the future comparing:

import { css } from '@pigment-css/react';
import Box from '@pigment-css/react/Box';

I think we should pick one way of import.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer import { Box } from '@pigment-css/react'; over default import.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer that everything is on a subpath. We don't want to repeat the same mistake of having barrel file exports from the start when we have control. Otherwise later, it'd harder to get the changes to be adopted by the user.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, let's use default export for Box. I added a task to move other APIs to the subpath before the stable beta release.

import routes from '~react-pages';
import Layout from '../../Layout';

Expand All @@ -17,33 +17,35 @@ export default function MaterialIndex() {
<div>
<h1>Material UI Components</h1>
<nav>
<ul
className={css({
<Box
as="ul"
sx={{
margin: 0,
marginBlock: '1rem',
padding: 0,
paddingLeft: '1.5rem',
display: 'flex',
flexDirection: 'column',
gap: '0.5rem',
})}
}}
>
{childRoutes
.filter((item) => !!item.path)
.map((item) => (
<li key={item.path}>
<Link
<Box
as={Link}
to={`/material-ui/${item.path}`}
className={css({
sx={{
textDecoration: 'underline',
fontSize: '17px',
})}
}}
>
{item.path}
</Link>
</Box>
</li>
))}
</ul>
</Box>
</nav>
</div>
</Layout>
Expand Down
2 changes: 1 addition & 1 deletion packages/pigment-css-react/src/Box.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ export interface PolymorphicComponent<BaseProps extends BaseDefaultProps>

declare const Box: PolymorphicComponent<{}>;

export { Box };
export default Box;
4 changes: 3 additions & 1 deletion packages/pigment-css-react/src/Box.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable react/prop-types */
import * as React from 'react';

export const Box = React.forwardRef(
const Box = React.forwardRef(
(
{
as = 'div',
Expand Down Expand Up @@ -50,3 +50,5 @@ export const Box = React.forwardRef(
return <Component ref={ref} className={classes} style={styles} {...rest} />;
},
);

export default Box;
29 changes: 27 additions & 2 deletions packages/pigment-css-react/src/processors/sx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,31 @@ import { processCssObject } from '../utils/processCssObject';
import { cssFnValueToVariable } from '../utils/cssFnValueToVariable';
import BaseProcessor from './base-processor';

// @TODO: Maybe figure out a better way allow imports.
const allowedSxTransformImports = [`${process.env.PACKAGE_NAME}/Box`];

/**
* Specifically looks for whether the sx prop should be transformed or not.
* If it's a Pigment CSS styled component, the value of `argumentValue` will
* be a string className starting with "."
* In other cases, it explicitly checks if the import is allowed for sx transformation.
*/
function allowSxTransform(argumentExpression: ExpressionValue, argumentValue?: string) {
if (!argumentExpression) {
return false;
}
if (
argumentExpression.kind === ValueType.LAZY &&
argumentExpression.importedFrom?.some((i) => allowedSxTransformImports.includes(i))
) {
return true;
}
if (argumentValue && argumentValue[0] === '.') {
return true;
}
return false;
}

export class SxProcessor extends BaseProcessor {
sxArguments: ExpressionValue[] = [];

Expand Down Expand Up @@ -41,7 +66,7 @@ export class SxProcessor extends BaseProcessor {
}
}

if (!this.elementClassName || this.elementClassName[0] !== '.') {
if (!allowSxTransform(elementClassExpression, this.elementClassName)) {
return;
}

Expand Down Expand Up @@ -95,7 +120,7 @@ export class SxProcessor extends BaseProcessor {
doRuntimeReplacement() {
const t = this.astService;
// do not replace if sx prop is not a Pigment styled component
if (!this.elementClassName) {
if (this.artifacts.length === 0) {
return;
}
if (this.collectedVariables.length) {
Expand Down
13 changes: 13 additions & 0 deletions packages/pigment-css-react/tests/Box/box.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import path from 'node:path';
import { runTransformation, expect } from '../testUtils';

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

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

export function App() {
return (
<Box
as="ul"
sx={{
margin: 0,
marginBlock: '1rem',
padding: 0,
paddingLeft: '1.5rem',
display: 'flex',
flexDirection: 'column',
gap: '0.5rem',
}}
>
Hello Box
</Box>
);
}
9 changes: 9 additions & 0 deletions packages/pigment-css-react/tests/Box/fixtures/box.output.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.bc1d15y {
margin: 0;
margin-block: 1rem;
padding: 0;
padding-left: 1.5rem;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
8 changes: 8 additions & 0 deletions packages/pigment-css-react/tests/Box/fixtures/box.output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Box from '@pigment-css/react/Box';
export function App() {
return (
<Box as="ul" sx={'bc1d15y'}>
Hello Box
</Box>
);
}
Loading