styled-components-to-stylex-codemod 0.0.27 → 0.0.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/transform.mjs +29 -42
  2. package/package.json +1 -1
@@ -719,6 +719,16 @@ function unwrapLogicalFallback(expr) {
719
719
  return null;
720
720
  }
721
721
  /**
722
+ * Returns true when `expr` is a `??` / `||` logical expression whose
723
+ * right-hand side is a non-literal value (e.g., `props.fallbackColor`).
724
+ *
725
+ * Used to bail on theme resolution when the fallback references a runtime
726
+ * value the user depends on — dropping it silently would change semantics.
727
+ */
728
+ function hasNonLiteralLogicalFallback(expr) {
729
+ return isLogicalExpressionNode(expr) && (expr.operator === "??" || expr.operator === "||") && literalToStaticValue(expr.right) === null;
730
+ }
731
+ /**
722
732
  * Type guard for ConditionalExpression nodes.
723
733
  */
724
734
  function isConditionalExpressionNode(node) {
@@ -4542,6 +4552,14 @@ function printNode(node) {
4542
4552
  function areAllValuesSame(values) {
4543
4553
  return values.length > 1 && values.every((value) => value === values[0]);
4544
4554
  }
4555
+ /**
4556
+ * Shorthands that StyleX requires to be fully expanded to physical longhands.
4557
+ * Unlike `padding`/`margin` (which StyleX's Babel plugin can expand internally),
4558
+ * `scrollPadding`/`scrollMargin` and their logical forms (Block/Inline) are not
4559
+ * recognized by `@stylexjs/valid-styles` and must always be written as
4560
+ * Top/Right/Bottom/Left.
4561
+ */
4562
+ const PHYSICAL_ONLY_SHORTHANDS = new Set(["scrollMargin", "scrollPadding"]);
4545
4563
  function expandQuadValues(values) {
4546
4564
  const top = values[0] ?? "";
4547
4565
  const right = values[1] ?? top;
@@ -4573,12 +4591,13 @@ function splitDirectionalProperty(args) {
4573
4591
  const bottom = values[2] ?? top;
4574
4592
  const left = values[3] ?? right;
4575
4593
  const withImportant = (value) => important ? `${value} !important` : value;
4576
- if (values.length === 1 && !important && !alwaysExpand) return [{
4594
+ const physicalOnly = PHYSICAL_ONLY_SHORTHANDS.has(prop);
4595
+ if (values.length === 1 && !important && !alwaysExpand && !physicalOnly) return [{
4577
4596
  prop,
4578
4597
  value: withImportant(top)
4579
4598
  }];
4580
4599
  const quad = expandQuadValues(values);
4581
- if (important) return [
4600
+ if (important || physicalOnly) return [
4582
4601
  {
4583
4602
  prop: `${prop}Top`,
4584
4603
  value: withImportant(quad[0])
@@ -15059,8 +15078,8 @@ function createThemeResolvers(args) {
15059
15078
  const themeAccessExpr = unwrapLogicalFallback(bodyExpr) ?? bodyExpr;
15060
15079
  const direct = resolveThemeValue(themeAccessExpr, cssProperty);
15061
15080
  if (direct) {
15062
- if (isDirectionalThemeResult(direct)) return direct;
15063
- return wrapWithLogicalFallback(direct, bodyExpr, j);
15081
+ if (hasNonLiteralLogicalFallback(bodyExpr)) return null;
15082
+ return direct;
15064
15083
  }
15065
15084
  const paramName = expr.params?.[0]?.type === "Identifier" ? expr.params[0].name : null;
15066
15085
  const unwrap = (node) => {
@@ -15094,8 +15113,8 @@ function createThemeResolvers(args) {
15094
15113
  if (!themePath) return null;
15095
15114
  const resolved = resolveThemePath(themePath, getNodeLocStart(unwrapped) ?? void 0, cssProperty);
15096
15115
  if (!resolved) return null;
15097
- if (isDirectionalThemeResult(resolved)) return resolved;
15098
- return wrapWithLogicalFallback(resolved, bodyExpr, j);
15116
+ if (hasNonLiteralLogicalFallback(bodyExpr)) return null;
15117
+ return resolved;
15099
15118
  };
15100
15119
  return {
15101
15120
  hasLocalThemeBinding,
@@ -15104,20 +15123,6 @@ function createThemeResolvers(args) {
15104
15123
  };
15105
15124
  }
15106
15125
  /**
15107
- * If `originalExpr` was a logical fallback (`X ?? "default"` / `X || "default"`),
15108
- * wraps the resolved AST node in a LogicalExpression preserving the original
15109
- * operator and fallback value.
15110
- *
15111
- * Returns null if the fallback (RHS) is not a static literal, because dynamic
15112
- * references (e.g., `props.fallbackColor`) would be invalid in a static
15113
- * `stylex.create()` context where `props` is not in scope.
15114
- */
15115
- function wrapWithLogicalFallback(resolved, originalExpr, j) {
15116
- if (!isLogicalExpressionNode(originalExpr) || originalExpr.operator !== "??" && originalExpr.operator !== "||") return resolved;
15117
- if (literalToStaticValue(originalExpr.right) === null) return null;
15118
- return j.logicalExpression(originalExpr.operator, resolved, originalExpr.right);
15119
- }
15120
- /**
15121
15126
  * Type guard for the internal `__directional` tagged result.
15122
15127
  */
15123
15128
  function isDirectionalThemeResult(value) {
@@ -18255,11 +18260,10 @@ function tryResolveThemeAccess(node, ctx) {
18255
18260
  type: "resolvedDirectional",
18256
18261
  directional: res.directional
18257
18262
  };
18258
- const resultExpr = appendLogicalFallback(expr.body, res.expr);
18259
- if (resultExpr === null) return null;
18263
+ if (hasNonLiteralLogicalFallback(expr.body)) return null;
18260
18264
  return {
18261
18265
  type: "resolvedValue",
18262
- expr: resultExpr,
18266
+ expr: res.expr,
18263
18267
  imports: res.imports
18264
18268
  };
18265
18269
  }
@@ -18272,8 +18276,8 @@ function tryResolveThemeAccess(node, ctx) {
18272
18276
  * (LogicalExpression with `??` or `||` and theme access on the left)
18273
18277
  *
18274
18278
  * Returns the MemberExpression node, or null if the pattern doesn't match.
18275
- * The fallback (right side of `??`/`||`) is preserved by the caller via
18276
- * `appendLogicalFallback` so users can review and delete it.
18279
+ * The fallback (right side of `??`/`||`) is dropped because StyleX `defineVars`
18280
+ * tokens always resolve at runtime.
18277
18281
  */
18278
18282
  function extractThemeMemberExpression(body) {
18279
18283
  if (!body || typeof body !== "object") return null;
@@ -18840,23 +18844,6 @@ function hasBooleanBranch(node) {
18840
18844
  if (n.type === "Literal" && typeof n.value === "boolean") return true;
18841
18845
  return false;
18842
18846
  }
18843
- /**
18844
- * If `body` is a logical fallback expression (`X ?? "default"` / `X || "default"`),
18845
- * appends the operator and fallback literal to the resolved expression string.
18846
- *
18847
- * Returns `null` when the body IS a logical expression but the fallback is non-literal
18848
- * (e.g., `props.fallbackColor`, `null`, `undefined`), signalling to the caller that
18849
- * it's unsafe to drop the fallback — the caller should bail instead of resolving.
18850
- *
18851
- * Returns `resolvedExpr` unchanged when the body is NOT a logical expression (no
18852
- * fallback to preserve).
18853
- */
18854
- function appendLogicalFallback(body, resolvedExpr) {
18855
- if (!isLogicalExpressionNode(body) || body.operator !== "??" && body.operator !== "||") return resolvedExpr;
18856
- const fallback = literalToStaticValue(body.right);
18857
- if (fallback === null) return null;
18858
- return `${resolvedExpr} ${body.operator} ${JSON.stringify(fallback)}`;
18859
- }
18860
18847
 
18861
18848
  //#endregion
18862
18849
  //#region src/internal/lower-rules/template-literals.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "styled-components-to-stylex-codemod",
3
- "version": "0.0.27",
3
+ "version": "0.0.28",
4
4
  "description": "Codemod to transform styled-components to StyleX",
5
5
  "keywords": [
6
6
  "codemod",