"use client"; import { useCart, useCartForm } from "@/lib/cart"; import { shopifyImageUrl } from "@/lib/image"; import { formatPrice } from "@/lib/money"; /** * A cart line, derived from the typed `useCart` binding (F3: consume typed data, * no hand-rolled parallel shape). Narrowed field access stays tolerant of the * gql.tada-inferred merchandise union via optional chaining * (`hydrogen-cart-ui` / `references/react.md`). */ type CartState = Parameters[0]>[0]; type CartLine = CartState["data"]["lines"]["nodes"][number]; /** * Shared cart line-item form — used by both the cart drawer and the `/cart` * page (`hydrogen-cart-ui` / `hydrogen-cart-drawer`). Preserves the * progressive-enhancement form contract: hidden `register("set")`, scoped * `register("lineId", { value })`, and a real editable quantity input from * `register("quantity", { value, interactive: true })`. Increase/decrease/remove * are additional submit controls, not replacements. */ export function CartLineItem({ line }: { line: CartLine }) { const { formProps, register } = useCartForm(); const pendingLines = useCart((state) => state.pending.lines); const isPending = pendingLines.has(line.id); const merchandise = line.merchandise; const productTitle = merchandise?.product?.title ?? merchandise?.title ?? "Product"; const productHandle = merchandise?.product?.handle; const selectedOptions = merchandise?.selectedOptions ?? []; const variantSubtitle = selectedOptions.map((option) => option.value).join(" / "); const totalAmount = line.cost.totalAmount; const compareAt = line.cost.compareAtAmountPerQuantity ?? null; const onSale = compareAt && Number(compareAt.amount) > Number(totalAmount.amount); return (
{merchandise?.image ? ( {merchandise.image.altText ) : null}
{productHandle ? ( {productTitle} ) : (

{productTitle}

)} {variantSubtitle ? (

{variantSubtitle}

) : null}

{onSale ? ( {formatPrice(totalAmount)} ) : ( formatPrice(totalAmount) )} {onSale && compareAt ? ( <> {" "} {formatPrice(compareAt)} ) : null}

); }