* Apply move to a framer-motion element by modifying the animate prop's existing x/y value. * Only called when detectMoveMechanism confirmed the animate prop already has the axis prop.
(nodePath: any, op: Extract<BatchOperation, { op: "moveSpacing" }>)
| 1030 | * Only called when detectMoveMechanism confirmed the animate prop already has the axis prop. |
| 1031 | */ |
| 1032 | function applyFramerMotionMove(nodePath: any, op: Extract<BatchOperation, { op: "moveSpacing" }>): string | undefined { |
| 1033 | const attrs = nodePath.node.openingElement?.attributes ?? []; |
| 1034 | const animateProp = attrs.find( |
| 1035 | (a: any) => a.type === "JSXAttribute" && a.name?.name === "animate" |
| 1036 | ); |
| 1037 | if (animateProp?.value?.type !== "JSXExpressionContainer") { |
| 1038 | return "animate prop not found or not an expression"; |
| 1039 | } |
| 1040 | |
| 1041 | const expr = animateProp.value.expression; |
| 1042 | if (expr.type !== "ObjectExpression") { |
| 1043 | return "Cannot modify framer-motion animate prop (not an inline object)"; |
| 1044 | } |
| 1045 | |
| 1046 | const propName = op.axis === "x" ? "x" : "y"; |
| 1047 | const existingProp = expr.properties.find( |
| 1048 | (p: any) => p.type === "ObjectProperty" && p.key?.name === propName |
| 1049 | ); |
| 1050 | |
| 1051 | if (!existingProp) { |
| 1052 | // Shouldn't happen — detectMoveMechanism verified this exists |
| 1053 | return `No ${propName} property in animate prop`; |
| 1054 | } |
| 1055 | |
| 1056 | // Read current numeric value (handles positive literals and unary negation) |
| 1057 | const currentValue = existingProp.value?.type === "NumericLiteral" |
| 1058 | ? existingProp.value.value |
| 1059 | : (existingProp.value?.type === "UnaryExpression" && existingProp.value.operator === "-" |
| 1060 | ? -(existingProp.value.argument?.value ?? 0) |
| 1061 | : 0); |
| 1062 | |
| 1063 | const newValue = currentValue + op.pxDelta; |
| 1064 | |
| 1065 | // Write back — use UnaryExpression for negative values to produce "y: -160" not "y: -160" |
| 1066 | if (newValue < 0) { |
| 1067 | existingProp.value = { |
| 1068 | type: "UnaryExpression", |
| 1069 | operator: "-", |
| 1070 | prefix: true, |
| 1071 | argument: { type: "NumericLiteral", value: Math.abs(newValue) }, |
| 1072 | }; |
| 1073 | } else { |
| 1074 | existingProp.value = { type: "NumericLiteral", value: newValue }; |
| 1075 | } |
| 1076 | |
| 1077 | return undefined; |
| 1078 | } |
| 1079 | |
| 1080 | // ── Main entry point ───────────────────────────────────────────────────── |
| 1081 |