Skip to content

Commit 39eb55a

Browse files
skovhusclaude
andcommitted
ref: rename to usePhysicalProperties opt-out, default to logical properties
Logical properties (paddingBlock/paddingInline) are now the default for 2-value shorthand expansion, matching StyleX's ESLint plugin recommendations. Use `usePhysicalProperties: true` in the adapter to opt out and get physical properties (paddingTop/paddingRight/paddingBottom/paddingLeft) instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 5b0c524 commit 39eb55a

95 files changed

Lines changed: 283 additions & 557 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/__tests__/transform.test.ts

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3987,21 +3987,19 @@ export const App = () => <Input readOnly value="test" />;
39873987
{ adapter: fixtureAdapter },
39883988
);
39893989
expect(result.code).not.toBeNull();
3990-
// The base has physical longhands (from "8px 12px").
3990+
// The base has logical longhands (from "8px 12px" → paddingBlock/paddingInline).
39913991
// The readonly block has padding: 0 which should be expanded to match.
3992-
expect(result.code).toContain("paddingTop");
3993-
expect(result.code).toContain("paddingRight");
3994-
expect(result.code).toContain("paddingBottom");
3995-
expect(result.code).toContain("paddingLeft");
3992+
expect(result.code).toContain("paddingBlock");
3993+
expect(result.code).toContain("paddingInline");
39963994
// The readonly style should NOT have the shorthand "padding" since it conflicts
3997-
// with the base's physical longhands.
3995+
// with the base's logical longhands.
39983996
const readonlyMatch = result.code!.match(/inputReadonly:\s*\{([^}]+)\}/);
39993997
expect(readonlyMatch).toBeTruthy();
40003998
const readonlyBlock = readonlyMatch![1]!;
40013999
// Should have expanded longhands, not shorthand
4002-
expect(readonlyBlock).not.toMatch(/\bpadding\b(?!Top|Right|Bottom|Left)/);
4003-
expect(readonlyBlock).toContain("paddingTop");
4004-
expect(readonlyBlock).toContain("paddingLeft");
4000+
expect(readonlyBlock).not.toMatch(/\bpadding\b(?!Block|Inline)/);
4001+
expect(readonlyBlock).toContain("paddingBlock");
4002+
expect(readonlyBlock).toContain("paddingInline");
40054003
});
40064004
});
40074005

@@ -4059,18 +4057,16 @@ export const App = () => <Input />;
40594057
);
40604058
expect(result.code).not.toBeNull();
40614059
// The base has paddingBlock (logical). The conditional has padding: 8px 12px.
4062-
// The expansion should produce physical longhands: paddingTop: 8, paddingRight: 12, etc.
4063-
expect(result.code).toContain("paddingTop: 8");
4064-
expect(result.code).toContain("paddingRight: 12");
4065-
expect(result.code).toContain("paddingBottom: 8");
4066-
expect(result.code).toContain("paddingLeft: 12");
4060+
// Both expand to logical longhands (default), so no conflict normalization needed.
4061+
expect(result.code).toContain("paddingBlock: 8");
4062+
expect(result.code).toContain("paddingInline: 12");
40674063
// Should NOT have the unsplit value
40684064
expect(result.code).not.toContain('"8px 12px"');
40694065
});
40704066
});
40714067

4072-
describe("useLogicalProperties adapter option", () => {
4073-
it("should expand 2-value padding to logical properties when enabled", () => {
4068+
describe("usePhysicalProperties adapter option", () => {
4069+
it("should expand 2-value padding to logical properties by default", () => {
40744070
const source = `
40754071
import styled from "styled-components";
40764072
@@ -4083,7 +4079,7 @@ export const App = () => <Box>test</Box>;
40834079
const result = transformWithWarnings(
40844080
{ source, path: "test.tsx" },
40854081
{ jscodeshift: j, j, stats: () => {}, report: () => {} },
4086-
{ adapter: { ...fixtureAdapter, useLogicalProperties: true } },
4082+
{ adapter: fixtureAdapter },
40874083
);
40884084
expect(result.code).not.toBeNull();
40894085
expect(result.code).toContain("paddingBlock");
@@ -4092,7 +4088,7 @@ export const App = () => <Box>test</Box>;
40924088
expect(result.code).not.toContain("paddingRight");
40934089
});
40944090

4095-
it("should expand 2-value padding to physical properties when disabled (default)", () => {
4091+
it("should expand 2-value padding to physical properties when usePhysicalProperties is true", () => {
40964092
const source = `
40974093
import styled from "styled-components";
40984094
@@ -4105,7 +4101,7 @@ export const App = () => <Box>test</Box>;
41054101
const result = transformWithWarnings(
41064102
{ source, path: "test.tsx" },
41074103
{ jscodeshift: j, j, stats: () => {}, report: () => {} },
4108-
{ adapter: fixtureAdapter },
4104+
{ adapter: { ...fixtureAdapter, usePhysicalProperties: true } },
41094105
);
41104106
expect(result.code).not.toBeNull();
41114107
expect(result.code).toContain("paddingTop");

src/adapter.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -725,16 +725,17 @@ export interface Adapter {
725725
useSxProp: boolean;
726726

727727
/**
728-
* Use CSS logical properties (`paddingBlock`/`paddingInline`) instead of physical
729-
* properties (`paddingTop`/`paddingRight`/`paddingBottom`/`paddingLeft`) when expanding
728+
* Use physical CSS properties (`paddingTop`/`paddingRight`/`paddingBottom`/`paddingLeft`)
729+
* instead of logical properties (`paddingBlock`/`paddingInline`) when expanding
730730
* 2-value CSS shorthands like `padding: 4px 8px`.
731731
*
732-
* Enable this for codebases that support RTL (right-to-left) layouts, where logical
733-
* properties automatically adapt to the writing direction.
732+
* By default, the codemod uses logical properties which adapt to the writing direction
733+
* (RTL/LTR), matching StyleX's ESLint plugin recommendations. Enable this if your
734+
* codebase does not need RTL support and you prefer physical properties.
734735
*
735736
* @default false
736737
*/
737-
useLogicalProperties?: boolean;
738+
usePhysicalProperties?: boolean;
738739
}
739740

740741
// ────────────────────────────────────────────────────────────────────────────
@@ -768,7 +769,7 @@ export interface AdapterInput {
768769
styleMerger: Adapter["styleMerger"];
769770
themeHook?: Adapter["themeHook"];
770771
useSxProp: Adapter["useSxProp"];
771-
useLogicalProperties?: Adapter["useLogicalProperties"];
772+
usePhysicalProperties?: Adapter["usePhysicalProperties"];
772773
}
773774

774775
// ────────────────────────────────────────────────────────────────────────────
@@ -837,8 +838,8 @@ export interface AdapterInput {
837838
* // Emit sx={} JSX attributes instead of {...stylex.props()} spreads (requires StyleX ≥0.18)
838839
* useSxProp: false,
839840
*
840-
* // Use logical properties (paddingBlock/paddingInline) for 2-value shorthands (RTL support)
841-
* useLogicalProperties: false,
841+
* // Opt out of logical properties — use paddingTop/Right/Bottom/Left instead of Block/Inline
842+
* // usePhysicalProperties: true,
842843
*
843844
* // Optional: customize runtime theme hook import/call used by emitted wrappers
844845
* themeHook: {

src/internal/css-prop-mapping.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export { isCssShorthandProperty, setUseLogicalProperties, getUseLogicalPropertie
1111
type StylexPropDecl = { prop: string; value: CssValue };
1212

1313
/** Module-level flag controlling whether 2-value shorthand expansion uses logical properties. */
14-
let useLogicalProperties = false;
14+
let useLogicalProperties = true;
1515

1616
function setUseLogicalProperties(value: boolean): void {
1717
useLogicalProperties = value;

src/internal/stylex-shorthands.test.ts

Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,10 @@ describe("splitDirectionalProperty", () => {
2727
]);
2828
});
2929

30-
it("uses physical longhands for two-value shorthand", () => {
30+
it("uses logical longhands for two-value shorthand (default)", () => {
3131
expect(splitDirectionalProperty({ prop: "padding", rawValue: "4px 8px" })).toEqual([
32-
{ prop: "paddingTop", value: "4px" },
33-
{ prop: "paddingRight", value: "8px" },
34-
{ prop: "paddingBottom", value: "4px" },
35-
{ prop: "paddingLeft", value: "8px" },
32+
{ prop: "paddingBlock", value: "4px" },
33+
{ prop: "paddingInline", value: "8px" },
3634
]);
3735
});
3836

@@ -85,26 +83,14 @@ describe("splitDirectionalProperty", () => {
8583
expect(result[3]!.prop).toBe("paddingInlineStart");
8684
});
8785

88-
it("uses logical longhands for two-value shorthand when useLogical is true", () => {
86+
it("uses physical longhands for two-value shorthand when useLogical is false", () => {
8987
expect(
90-
splitDirectionalProperty({ prop: "padding", rawValue: "4px 8px", useLogical: true }),
88+
splitDirectionalProperty({ prop: "padding", rawValue: "4px 8px", useLogical: false }),
9189
).toEqual([
92-
{ prop: "paddingBlock", value: "4px" },
93-
{ prop: "paddingInline", value: "8px" },
94-
]);
95-
});
96-
97-
it("uses physical longhands for three-value shorthand even when useLogical is true", () => {
98-
const result = splitDirectionalProperty({
99-
prop: "margin",
100-
rawValue: "4px 8px 12px",
101-
useLogical: true,
102-
});
103-
expect(result).toEqual([
104-
{ prop: "marginTop", value: "4px" },
105-
{ prop: "marginRight", value: "8px" },
106-
{ prop: "marginBottom", value: "12px" },
107-
{ prop: "marginLeft", value: "8px" },
90+
{ prop: "paddingTop", value: "4px" },
91+
{ prop: "paddingRight", value: "8px" },
92+
{ prop: "paddingBottom", value: "4px" },
93+
{ prop: "paddingLeft", value: "8px" },
10894
]);
10995
});
11096

@@ -122,10 +108,8 @@ describe("splitDirectionalProperty", () => {
122108
rawValue: "calc(100% - 20px) 10px",
123109
});
124110
expect(result).toEqual([
125-
{ prop: "marginTop", value: "calc(100% - 20px)" },
126-
{ prop: "marginRight", value: "10px" },
127-
{ prop: "marginBottom", value: "calc(100% - 20px)" },
128-
{ prop: "marginLeft", value: "10px" },
111+
{ prop: "marginBlock", value: "calc(100% - 20px)" },
112+
{ prop: "marginInline", value: "10px" },
129113
]);
130114
});
131115

src/internal/stylex-shorthands.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export function splitDirectionalProperty(args: {
118118
important = false,
119119
preferInline = false,
120120
alwaysExpand = false,
121-
useLogical = false,
121+
useLogical = true,
122122
} = args;
123123
const values = splitDirectionalShorthands(rawValue, false);
124124
const top = values[0] ?? "";

src/internal/transform-context.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ export class TransformContext {
125125
"transform(options) - missing `adapter` (if you run the jscodeshift transform directly, pass options.adapter)",
126126
);
127127

128-
setUseLogicalProperties(adapter.useLogicalProperties ?? false);
128+
setUseLogicalProperties(!(adapter.usePhysicalProperties ?? false));
129129

130130
const resolverImports = new Map<string, ImportSpec>();
131131
const {

test-cases/asProp-basic.output.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,8 @@ const styles = stylex.create({
6868
color: "#bf4f74",
6969
fontSize: "1em",
7070
margin: "1em",
71-
paddingTop: "0.25em",
72-
paddingRight: "1em",
73-
paddingBottom: "0.25em",
74-
paddingLeft: "1em",
71+
paddingBlock: "0.25em",
72+
paddingInline: "1em",
7573
borderWidth: 2,
7674
borderStyle: "solid",
7775
borderColor: "#bf4f74",

test-cases/asProp-forwarded.output.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,8 @@ export const App = () => (
4545
const styles = stylex.create({
4646
button: {
4747
display: "inline-block",
48-
paddingTop: 8,
49-
paddingRight: 16,
50-
paddingBottom: 8,
51-
paddingLeft: 16,
48+
paddingBlock: 8,
49+
paddingInline: 16,
5250
backgroundColor: "#bf4f74",
5351
color: "white",
5452
borderWidth: 0,

test-cases/basic-flowTypes.flow.output.jsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@ const styles = stylex.create({
2020
button: {
2121
backgroundColor: "#bf4f74",
2222
color: "white",
23-
paddingTop: 8,
24-
paddingRight: 16,
25-
paddingBottom: 8,
26-
paddingLeft: 16,
23+
paddingBlock: 8,
24+
paddingInline: 16,
2725
borderWidth: 0,
2826
borderStyle: "none",
2927
borderColor: "initial",

test-cases/basic-plainJavascript.output.jsx

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,16 @@ const styles = stylex.create({
1111
button: {
1212
backgroundColor: "#bf4f74",
1313
color: "white",
14-
paddingTop: 8,
15-
paddingRight: 16,
16-
paddingBottom: 8,
17-
paddingLeft: 16,
14+
paddingBlock: 8,
15+
paddingInline: 16,
1816
borderWidth: 0,
1917
borderStyle: "none",
2018
borderColor: "initial",
2119
borderRadius: 4,
2220
},
2321
card: {
24-
paddingTop: 16,
25-
paddingRight: 12,
26-
paddingBottom: 16,
27-
paddingLeft: 12,
22+
paddingBlock: 16,
23+
paddingInline: 12,
2824
backgroundColor: "white",
2925
borderRadius: 8,
3026
},

0 commit comments

Comments
 (0)