@cimplify/sdk 0.44.8 → 0.44.10

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.
package/dist/react.mjs CHANGED
@@ -6443,113 +6443,161 @@ function CartLineItemRow({
6443
6443
  const hasComposite = item.compositeSelections && item.compositeSelections.length > 0;
6444
6444
  const hasBundle = item.bundleSelections && item.bundleSelections.length > 0;
6445
6445
  const isOptimistic = item.isOptimistic === true;
6446
+ const lineTotal = parsePrice(unitPrice) * item.quantity;
6447
+ const imageUrl = item.product.image_url;
6448
+ const variantLabel = item.variant ? getVariantDisplayName(item.variant, item.product.name) : null;
6446
6449
  return /* @__PURE__ */ jsxs(
6447
6450
  "div",
6448
6451
  {
6449
6452
  "data-cimplify-cart-item": true,
6450
6453
  "data-optimistic": isOptimistic ? "true" : void 0,
6451
6454
  className: cn(
6452
- "flex items-start justify-between gap-4 py-4 border-b border-border last:border-b-0",
6455
+ "group relative flex gap-3 py-4 border-b border-border last:border-b-0 transition-opacity",
6456
+ isOptimistic && "opacity-60",
6453
6457
  classNames?.item
6454
6458
  ),
6455
6459
  children: [
6456
- /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-item-info": true, className: "flex-1 min-w-0 space-y-1", children: [
6457
- /* @__PURE__ */ jsx(
6458
- "span",
6460
+ /* @__PURE__ */ jsx(
6461
+ "div",
6462
+ {
6463
+ "data-cimplify-cart-item-image": true,
6464
+ className: "relative w-20 h-20 shrink-0 rounded-md overflow-hidden bg-muted",
6465
+ children: imageUrl ? /* @__PURE__ */ jsx(
6466
+ "img",
6467
+ {
6468
+ src: imageUrl,
6469
+ alt: "",
6470
+ className: "w-full h-full object-cover",
6471
+ loading: "lazy"
6472
+ }
6473
+ ) : /* @__PURE__ */ jsx("div", { className: "w-full h-full grid place-items-center text-muted-foreground/40", children: /* @__PURE__ */ jsx("svg", { className: "w-6 h-6", fill: "none", stroke: "currentColor", strokeWidth: "1.5", viewBox: "0 0 24 24", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 001.5-1.5V6a1.5 1.5 0 00-1.5-1.5H3.75A1.5 1.5 0 002.25 6v12a1.5 1.5 0 001.5 1.5zm10.5-11.25h.008v.008h-.008V8.25zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z" }) }) })
6474
+ }
6475
+ ),
6476
+ /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-item-info": true, className: "flex-1 min-w-0 flex flex-col", children: [
6477
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
6478
+ /* @__PURE__ */ jsx(
6479
+ "h3",
6480
+ {
6481
+ "data-cimplify-cart-item-name": true,
6482
+ className: cn("text-sm font-medium leading-tight m-0 truncate", classNames?.itemName),
6483
+ children: item.product.name
6484
+ }
6485
+ ),
6486
+ /* @__PURE__ */ jsx(
6487
+ "button",
6488
+ {
6489
+ type: "button",
6490
+ onClick: () => onRemove(item.id),
6491
+ "data-cimplify-cart-item-remove": true,
6492
+ className: cn(
6493
+ "shrink-0 -mr-1 -mt-1 grid place-items-center w-7 h-7 rounded-full text-muted-foreground/60 hover:text-foreground hover:bg-muted transition-colors",
6494
+ classNames?.removeButton
6495
+ ),
6496
+ "aria-label": `Remove ${item.product.name}`,
6497
+ children: /* @__PURE__ */ jsx("svg", { className: "w-3.5 h-3.5", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) })
6498
+ }
6499
+ )
6500
+ ] }),
6501
+ (variantLabel || item.addOnOptions && item.addOnOptions.length > 0 || hasComposite || hasBundle) && /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-item-pills": true, className: "flex flex-wrap gap-1.5 mt-1.5", children: [
6502
+ variantLabel && /* @__PURE__ */ jsx(
6503
+ "span",
6504
+ {
6505
+ "data-cimplify-cart-item-variant": true,
6506
+ className: "inline-flex items-center px-2 py-0.5 rounded-full bg-muted text-[11px] font-medium text-foreground",
6507
+ children: variantLabel
6508
+ }
6509
+ ),
6510
+ item.addOnOptions?.map((opt) => /* @__PURE__ */ jsxs(
6511
+ "span",
6512
+ {
6513
+ "data-cimplify-cart-item-addon": true,
6514
+ className: "inline-flex items-center px-2 py-0.5 rounded-full bg-muted text-[11px] font-medium text-muted-foreground",
6515
+ children: [
6516
+ "+ ",
6517
+ opt.name
6518
+ ]
6519
+ },
6520
+ opt.id
6521
+ )),
6522
+ (hasComposite || hasBundle) && /* @__PURE__ */ jsx(
6523
+ "span",
6524
+ {
6525
+ "data-cimplify-cart-item-badge": true,
6526
+ className: "inline-flex items-center px-2 py-0.5 rounded-full bg-primary/10 text-[11px] font-semibold uppercase tracking-wider text-primary",
6527
+ children: hasComposite ? "Custom" : "Bundle"
6528
+ }
6529
+ )
6530
+ ] }),
6531
+ item.specialInstructions && /* @__PURE__ */ jsxs(
6532
+ "p",
6459
6533
  {
6460
- "data-cimplify-cart-item-name": true,
6461
- className: cn("block font-medium", classNames?.itemName),
6462
- children: item.product.name
6534
+ "data-cimplify-cart-item-instructions": true,
6535
+ className: "mt-1.5 text-xs italic text-muted-foreground line-clamp-2",
6536
+ children: [
6537
+ "\\u201C",
6538
+ item.specialInstructions,
6539
+ "\\u201D"
6540
+ ]
6463
6541
  }
6464
6542
  ),
6465
- item.variant && /* @__PURE__ */ jsx("span", { "data-cimplify-cart-item-variant": true, className: "block text-xs text-muted-foreground", children: getVariantDisplayName(item.variant, item.product.name) }),
6466
- item.addOnOptions && item.addOnOptions.length > 0 && /* @__PURE__ */ jsxs("span", { "data-cimplify-cart-item-addons": true, className: "block text-xs text-muted-foreground", children: [
6467
- "+ ",
6468
- item.addOnOptions.map((opt) => opt.name).join(", ")
6469
- ] }),
6470
- (hasComposite || hasBundle) && /* @__PURE__ */ jsx("span", { "data-cimplify-cart-item-badge": true, children: hasComposite ? "Custom" : "Bundle" }),
6471
- item.specialInstructions && /* @__PURE__ */ jsx("span", { "data-cimplify-cart-item-instructions": true, className: "text-xs text-muted-foreground", children: item.specialInstructions }),
6472
- item.customerInputs && item.customerInputs.length > 0 && /* @__PURE__ */ jsx("div", { "data-cimplify-cart-customer-inputs": true, className: classNames?.customerInputs, children: item.customerInputs.map((input) => /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-input": true, children: [
6473
- /* @__PURE__ */ jsx("span", { "data-cimplify-cart-input-label": true, children: input.field_name }),
6474
- /* @__PURE__ */ jsx("span", { "data-cimplify-cart-input-value": true, children: input.field_type === INPUT_FIELD_TYPE.File || input.field_type === INPUT_FIELD_TYPE.Image ? String(input.value).split("/").pop() || "Uploaded file" : String(input.value) })
6543
+ item.customerInputs && item.customerInputs.length > 0 && /* @__PURE__ */ jsx("dl", { "data-cimplify-cart-customer-inputs": true, className: cn("mt-1.5 text-xs space-y-0.5", classNames?.customerInputs), children: item.customerInputs.map((input) => /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-input": true, className: "flex gap-1.5", children: [
6544
+ /* @__PURE__ */ jsxs("dt", { "data-cimplify-cart-input-label": true, className: "text-muted-foreground", children: [
6545
+ input.field_name,
6546
+ ":"
6547
+ ] }),
6548
+ /* @__PURE__ */ jsx("dd", { "data-cimplify-cart-input-value": true, className: "text-foreground m-0 truncate", children: input.field_type === INPUT_FIELD_TYPE.File || input.field_type === INPUT_FIELD_TYPE.Image ? String(input.value).split("/").pop() || "Uploaded file" : String(input.value) })
6475
6549
  ] }, input.field_id)) }),
6476
- (item.lineType === "service" || item.product.type === "service") && item.scheduledStart && /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-service-info": true, className: classNames?.serviceInfo, children: [
6550
+ (item.lineType === "service" || item.product.type === "service") && item.scheduledStart && /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-service-info": true, className: cn("mt-1.5 flex items-center gap-1.5 text-xs text-muted-foreground", classNames?.serviceInfo), children: [
6551
+ /* @__PURE__ */ jsx("svg", { className: "w-3.5 h-3.5 shrink-0", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" }) }),
6477
6552
  /* @__PURE__ */ jsxs("span", { children: [
6478
- "\u{1F4C5}",
6553
+ new Date(item.scheduledStart).toLocaleDateString(void 0, { month: "short", day: "numeric" }),
6554
+ " at",
6479
6555
  " ",
6480
- new Date(item.scheduledStart).toLocaleDateString(),
6481
- " at ",
6482
6556
  new Date(item.scheduledStart).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })
6483
6557
  ] }),
6484
- item.confirmationCode && /* @__PURE__ */ jsxs("span", { children: [
6485
- "Confirmation: ",
6486
- item.confirmationCode
6487
- ] }),
6488
- item.serviceStatus && /* @__PURE__ */ jsx("span", { "data-status": item.serviceStatus, children: item.serviceStatus })
6558
+ item.serviceStatus && /* @__PURE__ */ jsx("span", { "data-status": item.serviceStatus, className: "ml-auto px-1.5 py-0.5 rounded-full bg-muted text-[10px] uppercase tracking-wider", children: item.serviceStatus })
6489
6559
  ] }),
6490
- (item.lineType === "digital" || item.product.type === "digital") && /* @__PURE__ */ jsx("div", { "data-cimplify-cart-digital-info": true, className: classNames?.digitalInfo, children: /* @__PURE__ */ jsxs("span", { children: [
6491
- "\u26A1",
6492
- " Instant digital delivery"
6493
- ] }) }),
6494
- item.bundleResolved && /* @__PURE__ */ jsx("div", { "data-cimplify-cart-bundle-breakdown": true, className: classNames?.bundleBreakdown, children: item.bundleResolved.selections.map((sel) => /* @__PURE__ */ jsxs("div", { "data-product-type": sel.product_type, children: [
6495
- /* @__PURE__ */ jsxs("span", { children: [
6496
- sel.quantity,
6497
- "\xD7 ",
6498
- sel.product_name
6499
- ] }),
6500
- sel.product_type === "service" && sel.scheduling?.scheduled_start && /* @__PURE__ */ jsxs("span", { children: [
6501
- " \u2014 ",
6502
- new Date(sel.scheduling.scheduled_start).toLocaleDateString()
6503
- ] }),
6504
- sel.product_type === "digital" && /* @__PURE__ */ jsx("span", { children: " \u2014 Digital" })
6505
- ] }, sel.component_id)) }),
6506
- item.compositeResolved && /* @__PURE__ */ jsx("div", { "data-cimplify-cart-composite-breakdown": true, className: classNames?.compositeBreakdown, children: item.compositeResolved.selections.map((sel) => /* @__PURE__ */ jsxs("div", { "data-product-type": sel.product_type, children: [
6507
- /* @__PURE__ */ jsxs("span", { children: [
6508
- sel.quantity,
6509
- "\xD7 ",
6510
- sel.component_name
6511
- ] }),
6512
- sel.product_type === "service" && sel.scheduling?.scheduled_start && /* @__PURE__ */ jsxs("span", { children: [
6513
- " \u2014 ",
6514
- new Date(sel.scheduling.scheduled_start).toLocaleDateString()
6515
- ] })
6516
- ] }, sel.component_id)) }),
6517
- /* @__PURE__ */ jsx(
6518
- Price,
6560
+ (item.lineType === "digital" || item.product.type === "digital") && /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-digital-info": true, className: cn("mt-1.5 flex items-center gap-1 text-xs text-muted-foreground", classNames?.digitalInfo), children: [
6561
+ /* @__PURE__ */ jsx("svg", { className: "w-3.5 h-3.5 shrink-0", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M13 10V3L4 14h7v7l9-11h-7z" }) }),
6562
+ /* @__PURE__ */ jsx("span", { children: "Instant digital delivery" })
6563
+ ] }),
6564
+ (item.bundleResolved || item.compositeResolved) && /* @__PURE__ */ jsx(
6565
+ "ul",
6519
6566
  {
6520
- amount: unitPrice,
6521
- className: cn("block pt-1 text-sm font-semibold", classNames?.itemPrice)
6567
+ "data-cimplify-cart-composite-breakdown": item.compositeResolved ? "" : void 0,
6568
+ "data-cimplify-cart-bundle-breakdown": item.bundleResolved ? "" : void 0,
6569
+ className: cn("mt-1.5 pl-3 border-l border-border space-y-0.5 text-xs text-muted-foreground", item.compositeResolved ? classNames?.compositeBreakdown : classNames?.bundleBreakdown),
6570
+ children: (item.bundleResolved?.selections ?? item.compositeResolved?.selections ?? []).map((sel) => {
6571
+ const name = sel.product_name ?? sel.component_name ?? "";
6572
+ const compId = sel.component_id ?? `${name}-${sel.quantity}`;
6573
+ return /* @__PURE__ */ jsxs("li", { "data-product-type": sel.product_type, className: "flex items-baseline gap-1.5 m-0", children: [
6574
+ /* @__PURE__ */ jsxs("span", { className: "font-medium text-foreground/80", children: [
6575
+ sel.quantity,
6576
+ "\\u00D7"
6577
+ ] }),
6578
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: name })
6579
+ ] }, compId);
6580
+ })
6522
6581
  }
6523
- )
6524
- ] }),
6525
- /* @__PURE__ */ jsxs(
6526
- "div",
6527
- {
6528
- "data-cimplify-cart-item-controls": true,
6529
- className: cn("flex flex-col items-end gap-2 shrink-0", classNames?.quantity),
6530
- children: [
6531
- /* @__PURE__ */ jsx(
6532
- QuantitySelector,
6533
- {
6534
- value: item.quantity,
6535
- onChange: (qty) => onQuantityChange(item.id, qty),
6536
- min: 0
6537
- }
6538
- ),
6539
- /* @__PURE__ */ jsx(
6540
- "button",
6541
- {
6542
- type: "button",
6543
- onClick: () => onRemove(item.id),
6544
- "data-cimplify-cart-item-remove": true,
6545
- className: cn("text-xs text-muted-foreground hover:text-foreground hover:underline transition-colors", classNames?.removeButton),
6546
- "aria-label": `Remove ${item.product.name}`,
6547
- children: "Remove"
6548
- }
6549
- )
6550
- ]
6551
- }
6552
- )
6582
+ ),
6583
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 flex items-center justify-between gap-3", children: [
6584
+ /* @__PURE__ */ jsx(
6585
+ Price,
6586
+ {
6587
+ amount: lineTotal,
6588
+ className: cn("text-sm font-semibold tabular-nums", classNames?.itemPrice)
6589
+ }
6590
+ ),
6591
+ /* @__PURE__ */ jsx("div", { "data-cimplify-cart-item-controls": true, className: classNames?.quantity, children: /* @__PURE__ */ jsx(
6592
+ QuantitySelector,
6593
+ {
6594
+ value: item.quantity,
6595
+ onChange: (qty) => onQuantityChange(item.id, qty),
6596
+ min: 0
6597
+ }
6598
+ ) })
6599
+ ] })
6600
+ ] })
6553
6601
  ]
6554
6602
  }
6555
6603
  );
@@ -10684,42 +10732,65 @@ function DefaultCartLayout({
10684
10732
  className
10685
10733
  }) {
10686
10734
  if (cart.isEmpty) {
10687
- return /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-layout": "default", className: cn("text-center py-20", className), children: [
10688
- /* @__PURE__ */ jsx("svg", { className: "w-16 h-16 mx-auto text-muted-foreground/30", fill: "none", stroke: "currentColor", strokeWidth: "1", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" }) }),
10689
- /* @__PURE__ */ jsx("p", { className: "text-lg font-medium mt-4", children: "Your cart is empty" }),
10690
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Add some items to get started" }),
10691
- onContinueShopping && /* @__PURE__ */ jsx(
10735
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-layout": "default", className: cn("max-w-md mx-auto text-center py-24", className), children: [
10736
+ /* @__PURE__ */ jsxs("div", { className: "relative w-24 h-24 mx-auto mb-6", children: [
10737
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 rounded-full bg-muted" }),
10738
+ /* @__PURE__ */ jsx(
10739
+ "svg",
10740
+ {
10741
+ className: "relative w-12 h-12 m-auto top-1/2 -translate-y-1/2 text-muted-foreground/60",
10742
+ fill: "none",
10743
+ stroke: "currentColor",
10744
+ strokeWidth: "1.5",
10745
+ viewBox: "0 0 24 24",
10746
+ "aria-hidden": true,
10747
+ children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M16 11V7a4 4 0 00-8 0v4M5 9h14l-1 12H6L5 9z" })
10748
+ }
10749
+ )
10750
+ ] }),
10751
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold tracking-tight m-0", children: "Your cart is empty" }),
10752
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-2", children: "Browse the shop and add something you'll love." }),
10753
+ onContinueShopping && /* @__PURE__ */ jsxs(
10692
10754
  "button",
10693
10755
  {
10756
+ type: "button",
10694
10757
  onClick: onContinueShopping,
10695
- className: "text-sm font-medium text-primary mt-4 hover:underline",
10696
- children: "Continue shopping"
10758
+ className: "mt-6 inline-flex items-center gap-1.5 h-11 px-6 rounded-full bg-foreground text-background text-sm font-semibold hover:bg-foreground/90 active:scale-[0.99] transition-all",
10759
+ children: [
10760
+ "Shop now",
10761
+ /* @__PURE__ */ jsx("svg", { className: "w-3.5 h-3.5", fill: "none", stroke: "currentColor", strokeWidth: "2.5", viewBox: "0 0 24 24", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M14 5l7 7m0 0l-7 7m7-7H3" }) })
10762
+ ]
10697
10763
  }
10698
10764
  )
10699
10765
  ] });
10700
10766
  }
10701
- return /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-layout": "default", className: cn("space-y-6", className), children: [
10702
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
10703
- /* @__PURE__ */ jsxs("h1", { className: "text-2xl font-bold tracking-tight", children: [
10704
- "Your Cart (",
10767
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-layout": "default", className: cn("space-y-8", className), children: [
10768
+ /* @__PURE__ */ jsxs("header", { className: "flex items-baseline justify-between gap-4", children: [
10769
+ /* @__PURE__ */ jsx("h1", { className: "text-3xl sm:text-4xl font-bold tracking-tight m-0", children: "Cart" }),
10770
+ /* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground tabular-nums", children: [
10705
10771
  cart.itemCount,
10706
10772
  " ",
10707
- cart.itemCount === 1 ? "item" : "items",
10708
- ")"
10709
- ] }),
10710
- onContinueShopping && /* @__PURE__ */ jsx(
10711
- "button",
10712
- {
10713
- onClick: onContinueShopping,
10714
- className: "text-sm text-muted-foreground hover:text-foreground transition-colors",
10715
- children: "Continue shopping"
10716
- }
10717
- )
10773
+ cart.itemCount === 1 ? "item" : "items"
10774
+ ] })
10718
10775
  ] }),
10719
- /* @__PURE__ */ jsxs("div", { className: "grid lg:grid-cols-[1fr_380px] gap-8", children: [
10720
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(CartSummary, {}) }),
10721
- /* @__PURE__ */ jsx("div", { className: "lg:sticky lg:top-6 h-fit space-y-4", children: /* @__PURE__ */ jsxs("div", { className: "border border-border rounded-[14px] p-6 space-y-4", children: [
10722
- /* @__PURE__ */ jsx("h2", { className: "font-semibold", children: "Order Summary" }),
10776
+ /* @__PURE__ */ jsxs("div", { className: "grid lg:grid-cols-[1fr_360px] gap-10", children: [
10777
+ /* @__PURE__ */ jsxs("div", { children: [
10778
+ /* @__PURE__ */ jsx(CartSummary, {}),
10779
+ onContinueShopping && /* @__PURE__ */ jsxs(
10780
+ "button",
10781
+ {
10782
+ type: "button",
10783
+ onClick: onContinueShopping,
10784
+ className: "mt-6 inline-flex items-center gap-1.5 text-sm font-medium text-muted-foreground hover:text-foreground transition-colors",
10785
+ children: [
10786
+ /* @__PURE__ */ jsx("svg", { className: "w-3.5 h-3.5", fill: "none", stroke: "currentColor", strokeWidth: "2.5", viewBox: "0 0 24 24", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M10 19l-7-7m0 0l7-7m-7 7h18" }) }),
10787
+ "Continue shopping"
10788
+ ]
10789
+ }
10790
+ )
10791
+ ] }),
10792
+ /* @__PURE__ */ jsx("aside", { className: "lg:sticky lg:top-6 h-fit", children: /* @__PURE__ */ jsxs("div", { className: "rounded-2xl bg-muted/40 p-6 space-y-5", children: [
10793
+ /* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold uppercase tracking-[0.16em] text-muted-foreground m-0", children: "Summary" }),
10723
10794
  showDiscount && /* @__PURE__ */ jsx(
10724
10795
  DiscountInput,
10725
10796
  {
@@ -10728,28 +10799,34 @@ function DefaultCartLayout({
10728
10799
  onClear: onDiscountClear
10729
10800
  }
10730
10801
  ),
10731
- /* @__PURE__ */ jsxs("div", { className: "space-y-2 text-sm", children: [
10732
- /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
10733
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Subtotal" }),
10734
- /* @__PURE__ */ jsx(Price, { amount: cart.subtotal })
10802
+ /* @__PURE__ */ jsxs("dl", { className: "space-y-2 text-sm", children: [
10803
+ /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between", children: [
10804
+ /* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: "Subtotal" }),
10805
+ /* @__PURE__ */ jsx("dd", { className: "m-0 tabular-nums", children: /* @__PURE__ */ jsx(Price, { amount: cart.subtotal }) })
10735
10806
  ] }),
10736
- /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
10737
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Tax" }),
10738
- /* @__PURE__ */ jsx(Price, { amount: cart.tax })
10807
+ /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between", children: [
10808
+ /* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: "Tax" }),
10809
+ /* @__PURE__ */ jsx("dd", { className: "m-0 tabular-nums", children: /* @__PURE__ */ jsx(Price, { amount: cart.tax }) })
10739
10810
  ] }),
10740
- /* @__PURE__ */ jsxs("div", { className: "flex justify-between font-semibold text-base pt-2 border-t border-border", children: [
10741
- /* @__PURE__ */ jsx("span", { children: "Total" }),
10742
- /* @__PURE__ */ jsx(Price, { amount: cart.total })
10811
+ /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between pt-3 mt-1 border-t border-border", children: [
10812
+ /* @__PURE__ */ jsx("dt", { className: "font-semibold", children: "Total" }),
10813
+ /* @__PURE__ */ jsx("dd", { className: "m-0 text-lg font-bold tabular-nums", children: /* @__PURE__ */ jsx(Price, { amount: cart.total }) })
10743
10814
  ] })
10744
10815
  ] }),
10816
+ /* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: "Shipping calculated at checkout." }),
10745
10817
  /* @__PURE__ */ jsx(
10746
10818
  "button",
10747
10819
  {
10820
+ type: "button",
10748
10821
  onClick: onCheckout,
10749
- className: "w-full h-12 bg-foreground text-background font-medium text-sm rounded-lg hover:bg-foreground/90 transition-colors",
10822
+ className: "w-full h-12 rounded-full bg-foreground text-background font-semibold text-sm hover:bg-foreground/90 active:scale-[0.99] transition-all",
10750
10823
  children: checkoutLabel
10751
10824
  }
10752
- )
10825
+ ),
10826
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-1.5 text-[10px] text-muted-foreground/70 uppercase tracking-wider", children: [
10827
+ /* @__PURE__ */ jsx("svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" }) }),
10828
+ /* @__PURE__ */ jsx("span", { children: "Secure checkout" })
10829
+ ] })
10753
10830
  ] }) })
10754
10831
  ] })
10755
10832
  ] });
@@ -10846,28 +10923,52 @@ function useCartDrawer() {
10846
10923
  function CartDrawerProvider({ children, openOnAdd = true }) {
10847
10924
  const [isOpen, setIsOpen] = useState(false);
10848
10925
  const cart = useCart();
10849
- const [lastPending, setLastPending] = useState(0);
10926
+ const lastPendingRef = useRef(0);
10850
10927
  const open = useCallback(() => setIsOpen(true), []);
10851
10928
  const close = useCallback(() => setIsOpen(false), []);
10852
10929
  const toggle = useCallback(() => setIsOpen((v) => !v), []);
10853
10930
  useEffect(() => {
10854
10931
  if (!openOnAdd) return;
10855
- if (cart.pendingOpCount > lastPending && cart.pendingOpCount > 0) {
10932
+ if (cart.pendingOpCount > lastPendingRef.current && cart.pendingOpCount > 0) {
10856
10933
  setIsOpen(true);
10857
10934
  }
10858
- setLastPending(cart.pendingOpCount);
10859
- }, [cart.pendingOpCount, lastPending, openOnAdd]);
10935
+ lastPendingRef.current = cart.pendingOpCount;
10936
+ }, [cart.pendingOpCount, openOnAdd]);
10860
10937
  const value = useMemo(() => ({ isOpen, open, close, toggle }), [isOpen, open, close, toggle]);
10861
10938
  return /* @__PURE__ */ jsx(CartDrawerContext.Provider, { value, children });
10862
10939
  }
10940
+ function useAnimatedNumber(target, durationMs = 250) {
10941
+ const [value, setValue] = useState(target);
10942
+ const fromRef = useRef(target);
10943
+ const startRef = useRef(null);
10944
+ useEffect(() => {
10945
+ fromRef.current = value;
10946
+ startRef.current = null;
10947
+ let raf = 0;
10948
+ const tick = (t) => {
10949
+ if (startRef.current == null) startRef.current = t;
10950
+ const p = Math.min(1, (t - startRef.current) / durationMs);
10951
+ const eased = 1 - Math.pow(1 - p, 3);
10952
+ setValue(fromRef.current + (target - fromRef.current) * eased);
10953
+ if (p < 1) raf = requestAnimationFrame(tick);
10954
+ };
10955
+ raf = requestAnimationFrame(tick);
10956
+ return () => cancelAnimationFrame(raf);
10957
+ }, [target, durationMs]);
10958
+ return value;
10959
+ }
10863
10960
  function CartDrawer({
10864
10961
  onCheckout,
10865
10962
  onContinueShopping,
10866
- title = "Your cart",
10963
+ onShop,
10964
+ title = "Cart",
10965
+ freeShippingThreshold = 0,
10867
10966
  className
10868
10967
  }) {
10869
10968
  const { isOpen, close } = useCartDrawer();
10870
10969
  const cart = useCart();
10970
+ const subtotalNum = parsePrice(cart.subtotal);
10971
+ const animatedSubtotal = useAnimatedNumber(subtotalNum);
10871
10972
  useEffect(() => {
10872
10973
  if (!isOpen) return;
10873
10974
  const original = document.body.style.overflow;
@@ -10886,11 +10987,17 @@ function CartDrawer({
10886
10987
  onCheckout?.();
10887
10988
  };
10888
10989
  const handleContinue = () => {
10889
- if (onContinueShopping) {
10890
- onContinueShopping();
10891
- }
10990
+ onContinueShopping?.();
10892
10991
  close();
10893
10992
  };
10993
+ const handleShop = () => {
10994
+ onShop?.();
10995
+ close();
10996
+ };
10997
+ const showShippingBar = freeShippingThreshold > 0 && !cart.isEmpty;
10998
+ const remainingForShipping = Math.max(0, freeShippingThreshold - subtotalNum);
10999
+ const shippingProgress = freeShippingThreshold > 0 ? Math.min(100, subtotalNum / freeShippingThreshold * 100) : 0;
11000
+ const shippingUnlocked = subtotalNum >= freeShippingThreshold && freeShippingThreshold > 0;
10894
11001
  return /* @__PURE__ */ jsxs(
10895
11002
  "div",
10896
11003
  {
@@ -10907,7 +11014,7 @@ function CartDrawer({
10907
11014
  {
10908
11015
  onClick: close,
10909
11016
  className: cn(
10910
- "absolute inset-0 bg-foreground/40 backdrop-blur-sm transition-opacity duration-200",
11017
+ "absolute inset-0 bg-foreground/40 backdrop-blur-sm transition-opacity duration-300",
10911
11018
  isOpen ? "opacity-100" : "opacity-0"
10912
11019
  )
10913
11020
  }
@@ -10919,20 +11026,21 @@ function CartDrawer({
10919
11026
  "aria-modal": "true",
10920
11027
  "aria-label": title,
10921
11028
  className: cn(
10922
- "absolute top-0 right-0 h-full w-full sm:max-w-md bg-background shadow-2xl flex flex-col transition-transform duration-300 ease-out",
11029
+ "absolute top-0 right-0 h-full w-full sm:max-w-[480px] bg-background shadow-2xl flex flex-col",
11030
+ "transition-transform duration-300",
10923
11031
  isOpen ? "translate-x-0" : "translate-x-full",
11032
+ // ease-out cubic-bezier for a "pull" feel
11033
+ "[transition-timing-function:cubic-bezier(0.16,1,0.3,1)]",
10924
11034
  className
10925
11035
  ),
10926
11036
  children: [
10927
- /* @__PURE__ */ jsxs("header", { className: "flex items-center justify-between gap-4 px-6 py-4 border-b border-border shrink-0", children: [
10928
- /* @__PURE__ */ jsxs("h2", { className: "text-base font-semibold tracking-tight m-0", children: [
10929
- title,
10930
- cart.itemCount > 0 && /* @__PURE__ */ jsxs("span", { className: "ml-2 text-muted-foreground font-normal", children: [
10931
- "(",
11037
+ /* @__PURE__ */ jsxs("header", { className: "relative flex items-center justify-between gap-4 px-6 py-5 shrink-0", children: [
11038
+ /* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-2", children: [
11039
+ /* @__PURE__ */ jsx("h2", { className: "text-xl font-bold tracking-tight m-0", children: title }),
11040
+ cart.itemCount > 0 && /* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground tabular-nums", children: [
10932
11041
  cart.itemCount,
10933
11042
  " ",
10934
- cart.itemCount === 1 ? "item" : "items",
10935
- ")"
11043
+ cart.itemCount === 1 ? "item" : "items"
10936
11044
  ] })
10937
11045
  ] }),
10938
11046
  /* @__PURE__ */ jsx(
@@ -10941,52 +11049,55 @@ function CartDrawer({
10941
11049
  type: "button",
10942
11050
  onClick: close,
10943
11051
  "aria-label": "Close cart",
10944
- className: "grid place-items-center w-8 h-8 rounded-full hover:bg-muted text-muted-foreground hover:text-foreground transition-colors",
10945
- children: "\u2715"
11052
+ className: "grid place-items-center w-9 h-9 rounded-full hover:bg-muted text-muted-foreground hover:text-foreground transition-colors",
11053
+ children: /* @__PURE__ */ jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) })
10946
11054
  }
10947
11055
  )
10948
11056
  ] }),
10949
- /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto px-6 py-2", children: cart.isEmpty ? /* @__PURE__ */ jsx("div", { className: "h-full grid place-items-center text-center py-20", children: /* @__PURE__ */ jsxs("div", { children: [
11057
+ showShippingBar && /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-shipping-bar": true, className: "px-6 pb-4 shrink-0", children: [
11058
+ /* @__PURE__ */ jsx("div", { className: "flex items-baseline justify-between gap-2 mb-1.5 text-xs", children: shippingUnlocked ? /* @__PURE__ */ jsx("span", { className: "font-medium text-primary", children: "\u2713 Free shipping unlocked" }) : /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
11059
+ /* @__PURE__ */ jsx(Price, { amount: remainingForShipping, className: "font-semibold text-foreground" }),
11060
+ " away from free shipping"
11061
+ ] }) }),
11062
+ /* @__PURE__ */ jsx("div", { className: "h-1 rounded-full bg-muted overflow-hidden", children: /* @__PURE__ */ jsx(
11063
+ "div",
11064
+ {
11065
+ className: "h-full bg-primary transition-[width] duration-500 ease-out",
11066
+ style: { width: `${shippingProgress}%` }
11067
+ }
11068
+ ) })
11069
+ ] }),
11070
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto px-6", children: cart.isEmpty ? /* @__PURE__ */ jsx(EmptyState, { onShop: handleShop }) : /* @__PURE__ */ jsx(CartSummary, {}) }),
11071
+ !cart.isEmpty && /* @__PURE__ */ jsxs("footer", { className: "border-t border-border px-6 py-5 shrink-0 space-y-3 bg-background", children: [
11072
+ /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between", children: [
11073
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Subtotal" }),
11074
+ /* @__PURE__ */ jsx(Price, { amount: animatedSubtotal, className: "text-lg font-bold tabular-nums" })
11075
+ ] }),
11076
+ /* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: "Tax and shipping calculated at checkout." }),
11077
+ /* @__PURE__ */ jsxs(
11078
+ "button",
11079
+ {
11080
+ type: "button",
11081
+ onClick: handleCheckout,
11082
+ className: "w-full h-12 rounded-full bg-foreground text-background font-semibold text-sm hover:bg-foreground/90 active:scale-[0.99] transition-all",
11083
+ children: [
11084
+ "Checkout \u2014 ",
11085
+ /* @__PURE__ */ jsx(Price, { amount: cart.subtotal, className: "tabular-nums" })
11086
+ ]
11087
+ }
11088
+ ),
10950
11089
  /* @__PURE__ */ jsx(
10951
- "svg",
11090
+ "button",
10952
11091
  {
10953
- className: "w-12 h-12 mx-auto text-muted-foreground/30",
10954
- fill: "none",
10955
- stroke: "currentColor",
10956
- strokeWidth: "1",
10957
- viewBox: "0 0 24 24",
10958
- "aria-hidden": true,
10959
- children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z" })
11092
+ type: "button",
11093
+ onClick: handleContinue,
11094
+ className: "w-full text-xs font-medium text-muted-foreground hover:text-foreground transition-colors",
11095
+ children: "Continue shopping"
10960
11096
  }
10961
11097
  ),
10962
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium mt-3 mb-1", children: "Your cart is empty" }),
10963
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Add some items to get started" })
10964
- ] }) }) : /* @__PURE__ */ jsx(CartSummary, {}) }),
10965
- !cart.isEmpty && /* @__PURE__ */ jsxs("footer", { className: "border-t border-border px-6 py-4 space-y-3 shrink-0", children: [
10966
- /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between text-sm", children: [
10967
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Subtotal" }),
10968
- /* @__PURE__ */ jsx(Price, { amount: cart.subtotal, className: "font-semibold text-base" })
10969
- ] }),
10970
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Tax and delivery calculated at checkout." }),
10971
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 pt-1", children: [
10972
- /* @__PURE__ */ jsx(
10973
- "button",
10974
- {
10975
- type: "button",
10976
- onClick: handleCheckout,
10977
- className: "w-full h-11 rounded-md bg-foreground text-background font-medium text-sm hover:bg-foreground/90 transition-colors",
10978
- children: "Checkout"
10979
- }
10980
- ),
10981
- /* @__PURE__ */ jsx(
10982
- "button",
10983
- {
10984
- type: "button",
10985
- onClick: handleContinue,
10986
- className: "w-full h-10 text-xs font-medium text-muted-foreground hover:text-foreground transition-colors",
10987
- children: "Continue shopping"
10988
- }
10989
- )
11098
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-1.5 text-[10px] text-muted-foreground/70 uppercase tracking-wider pt-1", children: [
11099
+ /* @__PURE__ */ jsx("svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" }) }),
11100
+ /* @__PURE__ */ jsx("span", { children: "Secure checkout" })
10990
11101
  ] })
10991
11102
  ] })
10992
11103
  ]
@@ -10996,6 +11107,41 @@ function CartDrawer({
10996
11107
  }
10997
11108
  );
10998
11109
  }
11110
+ function EmptyState({ onShop }) {
11111
+ return /* @__PURE__ */ jsx("div", { "data-cimplify-cart-empty": true, className: "h-full grid place-items-center text-center py-16", children: /* @__PURE__ */ jsxs("div", { className: "space-y-5 max-w-[260px]", children: [
11112
+ /* @__PURE__ */ jsxs("div", { className: "relative w-20 h-20 mx-auto", children: [
11113
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 rounded-full bg-muted" }),
11114
+ /* @__PURE__ */ jsx(
11115
+ "svg",
11116
+ {
11117
+ className: "relative w-10 h-10 m-auto top-1/2 -translate-y-1/2 text-muted-foreground/60",
11118
+ fill: "none",
11119
+ stroke: "currentColor",
11120
+ strokeWidth: "1.5",
11121
+ viewBox: "0 0 24 24",
11122
+ "aria-hidden": true,
11123
+ children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M16 11V7a4 4 0 00-8 0v4M5 9h14l-1 12H6L5 9z" })
11124
+ }
11125
+ )
11126
+ ] }),
11127
+ /* @__PURE__ */ jsxs("div", { children: [
11128
+ /* @__PURE__ */ jsx("p", { className: "text-base font-semibold m-0", children: "Your cart is empty" }),
11129
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Discover something you'll love." })
11130
+ ] }),
11131
+ /* @__PURE__ */ jsxs(
11132
+ "button",
11133
+ {
11134
+ type: "button",
11135
+ onClick: onShop,
11136
+ className: "inline-flex items-center gap-1.5 h-11 px-6 rounded-full bg-foreground text-background text-sm font-semibold hover:bg-foreground/90 active:scale-[0.99] transition-all",
11137
+ children: [
11138
+ "Shop now",
11139
+ /* @__PURE__ */ jsx("svg", { className: "w-3.5 h-3.5", fill: "none", stroke: "currentColor", strokeWidth: "2.5", viewBox: "0 0 24 24", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M14 5l7 7m0 0l-7 7m7-7H3" }) })
11140
+ ]
11141
+ }
11142
+ )
11143
+ ] }) });
11144
+ }
10999
11145
  function CheckoutPage({
11000
11146
  title = "Checkout",
11001
11147
  onComplete,