Skip to content

Commit

Permalink
handle margin/padding shorthands in style props codemod (#7740)
Browse files Browse the repository at this point in the history
  • Loading branch information
reidbarber authored Feb 7, 2025
1 parent ff300df commit cc08a8d
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,56 @@ import { style } from "@react-spectrum/s2/style" with { type: "macro" };
})}>Test</Button>"
`;

exports[`Handles multi-value margin/padding shorthands 1`] = `
"import { style } from "@react-spectrum/s2/style" with { type: "macro" };
<>
<div className={style({
margin: "[10px]"
})}>Single Value Margin</div>
<div className={style({
marginY: "[10px]",
marginX: 16
})}>Two Value Margin</div>
<div className={style({
marginTop: "[10px]",
marginX: 16,
marginBottom: 20
})}>Three Value Margin</div>
<div className={style({
marginTop: "[10px]",
marginRight: 16,
marginBottom: 20,
marginLeft: 24
})}>Four Value Margin</div>
<div className={style({
padding: "[10px]"
})}>Single Value Padding</div>
<div className={style({
paddingY: "[10px]",
paddingX: 16
})}>Two Value Padding</div>
<div className={style({
paddingTop: "[10px]",
paddingX: 16,
paddingBottom: 20
})}>Three Value Padding</div>
<div className={style({
paddingTop: "[10px]",
paddingRight: 16,
paddingBottom: 20,
paddingLeft: 24
})}>Four Value Padding</div>
</>"
`;

exports[`Handles responsive style props 1`] = `
"import { TextField } from "@react-spectrum/s2";
import { style } from "@react-spectrum/s2/style" with { type: "macro" };
Expand Down
22 changes: 22 additions & 0 deletions packages/dev/codemods/src/s1-to-s2/__tests__/styleProps.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,25 @@ import { style } from "@react-spectrum/s2/style" with { type: "macro" };
<TextField label="Name" styles={style({width: 160})} />
`);

test('Handles multi-value margin/padding shorthands', `
import {View} from '@adobe/react-spectrum';
<>
<View margin="10px">Single Value Margin</View>
<View margin="10px 16px">Two Value Margin</View>
<View margin="10px 16px 20px">Three Value Margin</View>
<View margin="10px 16px 20px 24px">Four Value Margin</View>
<View padding="10px">Single Value Padding</View>
<View padding="10px 16px">Two Value Padding</View>
<View padding="10px 16px 20px">Three Value Padding</View>
<View padding="10px 16px 20px 24px">Four Value Padding</View>
</>
`);
72 changes: 72 additions & 0 deletions packages/dev/codemods/src/s1-to-s2/src/codemods/styleProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,17 @@ function getStylePropValue(prop: string, value: t.ObjectProperty['value'], eleme
case 'end':
case 'flexBasis': {
if (value.type === 'StringLiteral' || value.type === 'NumericLiteral') {
if (prop === 'margin' && value.type === 'StringLiteral' && /\s/.test(value.value)) {
// Check if it has multiple whitespace-separated values
let expansions = expandSpaceShorthand(prop, value.value, convertDimension);
if (!expansions) {
return null;
}
return {
macroValues: expansions
};
}

let val = convertDimension(value.value, 'space');
if (val != null) {
return {
Expand Down Expand Up @@ -316,6 +327,17 @@ function getStylePropValue(prop: string, value: t.ObjectProperty['value'], eleme
case 'paddingBottom':
if (element === 'View') {
if (value.type === 'StringLiteral' || value.type === 'NumericLiteral') {
if (prop === 'padding' && value.type === 'StringLiteral' && /\s/.test(value.value)) {
// Check if it has multiple whitespace-separated values
let expansions = expandSpaceShorthand(prop, value.value, convertDimension);
if (!expansions) {
return null;
}
return {
macroValues: expansions
};
}

let val = convertDimension(value.value, 'space');
if (val != null) {
return {
Expand Down Expand Up @@ -519,6 +541,56 @@ function handleProp(
}
}

function expandSpaceShorthand(
prop: string,
rawValue: string,
convertFn: (val: string | number, type: 'space' | 'size' | 'px') => any
) {
// Split on whitespace (e.g. "10px 16px" -> ["10px", "16px"])
let parts = rawValue.trim().split(/\s+/);

// One value => all sides
// Two values => vertical horizontal
// Three values => top, horizontal, bottom
// Four values => top, right, bottom, left
// Return keys and values in an array we can map to macroValues.
switch (parts.length) {
case 1: {
let val = convertFn(parts[0], 'space');
return [{key: prop, value: val}];
}
case 2: {
let [y, x] = parts;
return [
{key: `${prop}Y`, value: convertFn(y, 'space')},
{key: `${prop}X`, value: convertFn(x, 'space')}
];
}
case 3: {
// top horizontal bottom
let [top, x, bottom] = parts;
return [
{key: `${prop}Top`, value: convertFn(top, 'space')},
{key: `${prop}X`, value: convertFn(x, 'space')},
{key: `${prop}Bottom`, value: convertFn(bottom, 'space')}
];
}
case 4: {
// top right bottom left
let [top, right, bottom, left] = parts;
return [
{key: `${prop}Top`, value: convertFn(top, 'space')},
{key: `${prop}Right`, value: convertFn(right, 'space')},
{key: `${prop}Bottom`, value: convertFn(bottom, 'space')},
{key: `${prop}Left`, value: convertFn(left, 'space')}
];
}
default: {
return null;
}
}
}

export function transformStyleProps(path: NodePath<t.JSXElement>, element: string) {
let macroValues = new Map<string, object | string | number | boolean>;
let dynamicValues = new Map<string, t.ObjectProperty['value']>;
Expand Down

1 comment on commit cc08a8d

@rspbot
Copy link

@rspbot rspbot commented on cc08a8d Feb 7, 2025

Choose a reason for hiding this comment

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

Please sign in to comment.