Skip to content
Open
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
5 changes: 5 additions & 0 deletions .changeset/fix-styled-components-css-prop-nested-member.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@swc/plugin-styled-components": patch
---

Pass `css` prop interpolations such as `${SIZES[size].bottom}` through as props when a key further along the member chain is a local, instead of hoisting them out of the component's scope.
Original file line number Diff line number Diff line change
Expand Up @@ -1292,6 +1292,31 @@ var _StyledDiv = styled("div").withConfig({
"
`;

exports[`Should load styled-components wasm plugin correctly > Should transform transpile-css-prop-nested-member correctly 1`] = `
"import styled from 'styled-components';
const Box = styled.div\`\`;
var _StyledBox3 = styled(Box)\`bottom: \${SIZES[KEY].bottom};\`;
var _StyledBox2 = styled(Box)\`bottom: \${(p)=>p.$_css2};\`;
var _StyledBox = styled(Box)\`bottom: \${(p)=>p.$_css};\`;
const SIZES = {
small: {
bottom: '8px'
},
large: {
bottom: '16px'
}
};
const KEY = 'small';
export const Local = ({ size })=>/*#__PURE__*/ React.createElement(_StyledBox, {
$_css: SIZES[size].bottom
});
export const LocalCall = ({ size })=>/*#__PURE__*/ React.createElement(_StyledBox2, {
$_css2: SIZES.get(size).bottom
});
export const TopLevel = ()=>/*#__PURE__*/ React.createElement(_StyledBox3, null);
"
`;

exports[`Should load styled-components wasm plugin correctly > Should transform transpile-require-default correctly 1`] = `
"const styled_default = require("styled-components");
const TestNormal = styled.div.withConfig({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -663,22 +663,38 @@ fn is_direct_access<F>(expr: &Expr, is_top_level_ident: &F) -> bool
where
F: Fn(&Ident) -> bool,
{
if let Some(root) = trace_root_value(expr) {
match root {
Expr::Lit(_) => true,
Expr::Ident(id) if is_top_level_ident(id) => match expr {
Expr::Call(CallExpr { args, .. }) => args
match trace_root_value(expr) {
Some(Expr::Lit(_)) => true,
Some(Expr::Ident(id)) if is_top_level_ident(id) => {
has_only_direct_keys(expr, is_top_level_ident)
}
_ => false,
}
}

/// Whether every computed key and call argument along a member/call chain is
/// itself a direct access, so `SIZES[size].bottom` is not mistaken for a
/// module-level value.
fn has_only_direct_keys<F>(expr: &Expr, is_top_level_ident: &F) -> bool
where
F: Fn(&Ident) -> bool,
{
match expr {
Expr::Member(MemberExpr { obj, prop, .. }) => {
has_only_direct_keys(obj, is_top_level_ident)
&& match prop {
MemberProp::Computed(ComputedPropName { expr, .. }) => {
is_direct_access(expr, is_top_level_ident)
}
_ => true,
}
}
Expr::Call(CallExpr { callee, args, .. }) => {
matches!(callee, Callee::Expr(callee) if has_only_direct_keys(callee, is_top_level_ident))
&& args
.iter()
.all(|arg| -> bool { is_direct_access(&arg.expr, is_top_level_ident) }),
Expr::Member(MemberExpr {
prop: MemberProp::Computed(ComputedPropName { expr, .. }),
..
}) => is_direct_access(expr, is_top_level_ident),
_ => true,
},
_ => false,
.all(|arg| is_direct_access(&arg.expr, is_top_level_ident))
}
} else {
false
_ => true,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import styled from 'styled-components';

const Box = styled.div``;
const SIZES = { small: { bottom: '8px' }, large: { bottom: '16px' } };
const KEY = 'small';

export const Local = ({ size }) => <Box css={`bottom: ${SIZES[size].bottom};`} />;

export const LocalCall = ({ size }) => <Box css={`bottom: ${SIZES.get(size).bottom};`} />;

export const TopLevel = () => <Box css={`bottom: ${SIZES[KEY].bottom};`} />;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"ssr": false,
"displayName": false,
"transpileTemplateLiterals": false,
"minify": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import styled from 'styled-components';
const Box = styled.div``;
var _StyledBox3 = styled(Box)`bottom: ${SIZES[KEY].bottom};`;
var _StyledBox2 = styled(Box)`bottom: ${(p)=>p.$_css2};`;
var _StyledBox = styled(Box)`bottom: ${(p)=>p.$_css};`;
const SIZES = {
small: {
bottom: '8px'
},
large: {
bottom: '16px'
}
};
const KEY = 'small';
export const Local = ({ size })=><_StyledBox $_css={SIZES[size].bottom}/>;
export const LocalCall = ({ size })=><_StyledBox2 $_css2={SIZES.get(size).bottom}/>;
export const TopLevel = ()=><_StyledBox3/>;
Loading