@burdenoff/microfe-store 2026.915.2 → 2026.916.2

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.
@@ -20,6 +20,8 @@ interface CartDrawerProps {
20
20
  };
21
21
  }>;
22
22
  itemCount: number;
23
+ /** Cart-wide currency — see useBackendCart.ts's Cart type (one currency per cart). */
24
+ currency: string;
23
25
  subtotal: number;
24
26
  tax: number;
25
27
  total: number;
@@ -3,11 +3,11 @@ import { useTr as t } from "../../shared/hooks/useTr.js";
3
3
  import { Minus as n, Plus as r, ShoppingCart as i, Trash2 as a, X as o } from "lucide-react";
4
4
  import { Fragment as s, jsx as c, jsxs as l } from "react/jsx-runtime";
5
5
  //#region src/components/cart/CartDrawer.tsx
6
- var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, subtotal: h, tax: g, total: _, updateQuantity: v, removeProduct: y }) => {
7
- let b = t();
6
+ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, currency: h, subtotal: g, tax: _, total: v, updateQuantity: y, removeProduct: b }) => {
7
+ let x = t();
8
8
  return u ? /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ c("button", {
9
9
  type: "button",
10
- "aria-label": b("cart.closeCart", "Close cart"),
10
+ "aria-label": x("cart.closeCart", "Close cart"),
11
11
  className: "fixed inset-0 z-40 bg-bg-overlay/50 transition-opacity",
12
12
  onClick: d
13
13
  }), /* @__PURE__ */ c("div", {
@@ -23,7 +23,7 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
23
23
  /* @__PURE__ */ c(i, { className: "size-5 text-text-primary" }),
24
24
  /* @__PURE__ */ c("h2", {
25
25
  className: "text-lg font-semibold text-text-primary",
26
- children: b("cart.title", "Shopping Cart")
26
+ children: x("cart.title", "Shopping Cart")
27
27
  }),
28
28
  m > 0 && /* @__PURE__ */ c("span", {
29
29
  className: "rounded-full bg-bg-accent px-2 py-0.5 text-xs font-medium tabular-nums text-text-link",
@@ -33,7 +33,7 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
33
33
  }), /* @__PURE__ */ c("button", {
34
34
  type: "button",
35
35
  onClick: d,
36
- "aria-label": b("cart.closeCart", "Close cart"),
36
+ "aria-label": x("cart.closeCart", "Close cart"),
37
37
  className: "cursor-pointer rounded-lg p-2 text-text-muted transition-colors hover:bg-bg-sunken hover:text-text-primary",
38
38
  children: /* @__PURE__ */ c(o, { className: "size-5" })
39
39
  })]
@@ -41,7 +41,7 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
41
41
  /* @__PURE__ */ c("div", {
42
42
  className: "flex-1 overflow-y-auto px-4 sm:px-6 py-4",
43
43
  children: p.length === 0 ? /* @__PURE__ */ l("output", {
44
- "aria-label": b("cart.empty", "Your cart is empty"),
44
+ "aria-label": x("cart.empty", "Your cart is empty"),
45
45
  className: "flex h-full flex-col items-center justify-center text-center",
46
46
  children: [
47
47
  /* @__PURE__ */ c(i, {
@@ -50,11 +50,11 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
50
50
  }),
51
51
  /* @__PURE__ */ c("h3", {
52
52
  className: "mb-2 text-lg font-semibold text-text-primary",
53
- children: b("cart.empty", "Your cart is empty")
53
+ children: x("cart.empty", "Your cart is empty")
54
54
  }),
55
55
  /* @__PURE__ */ c("p", {
56
56
  className: "text-sm text-text-muted",
57
- children: b("cart.emptyHint", "Start shopping to add items to your cart")
57
+ children: x("cart.emptyHint", "Start shopping to add items to your cart")
58
58
  })
59
59
  ]
60
60
  }) : /* @__PURE__ */ c("div", {
@@ -76,7 +76,7 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
76
76
  children: [
77
77
  /* @__PURE__ */ c("h4", {
78
78
  className: "mb-1 font-semibold text-text-primary",
79
- children: t.productName || t.product?.name || b("common.product", "Product")
79
+ children: t.productName || t.product?.name || x("common.product", "Product")
80
80
  }),
81
81
  t.variantName && /* @__PURE__ */ c("p", {
82
82
  className: "mb-2 text-xs text-text-muted",
@@ -89,8 +89,8 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
89
89
  children: [
90
90
  /* @__PURE__ */ c("button", {
91
91
  type: "button",
92
- onClick: () => v(t.id, t.quantity - 1),
93
- "aria-label": b("cart.decreaseQuantity", "Decrease quantity of {{name}}", { name: t.productName || t.product?.name || b("common.item", "item") }),
92
+ onClick: () => y(t.id, t.quantity - 1),
93
+ "aria-label": x("cart.decreaseQuantity", "Decrease quantity of {{name}}", { name: t.productName || t.product?.name || x("common.item", "item") }),
94
94
  className: "cursor-pointer p-1.5 transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-50",
95
95
  disabled: t.quantity <= 1,
96
96
  children: /* @__PURE__ */ c(n, {
@@ -100,13 +100,13 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
100
100
  }),
101
101
  /* @__PURE__ */ c("span", {
102
102
  className: "min-w-[2rem] text-center text-sm font-medium",
103
- "aria-label": b("cart.quantity", "Quantity: {{quantity}}", { quantity: t.quantity }),
103
+ "aria-label": x("cart.quantity", "Quantity: {{quantity}}", { quantity: t.quantity }),
104
104
  children: t.quantity
105
105
  }),
106
106
  /* @__PURE__ */ c("button", {
107
107
  type: "button",
108
- onClick: () => v(t.id, t.quantity + 1),
109
- "aria-label": b("cart.increaseQuantity", "Increase quantity of {{name}}", { name: t.productName || t.product?.name || b("common.item", "item") }),
108
+ onClick: () => y(t.id, t.quantity + 1),
109
+ "aria-label": x("cart.increaseQuantity", "Increase quantity of {{name}}", { name: t.productName || t.product?.name || x("common.item", "item") }),
110
110
  className: "cursor-pointer p-1.5 transition-colors hover:bg-bg-sunken",
111
111
  children: /* @__PURE__ */ c(r, {
112
112
  className: "size-4",
@@ -116,8 +116,8 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
116
116
  ]
117
117
  }), /* @__PURE__ */ c("button", {
118
118
  type: "button",
119
- onClick: () => y(t.id),
120
- "aria-label": b("cart.removeItem", "Remove {{name}} from cart", { name: t.productName || t.product?.name || b("common.item", "item") }),
119
+ onClick: () => b(t.id),
120
+ "aria-label": x("cart.removeItem", "Remove {{name}} from cart", { name: t.productName || t.product?.name || x("common.item", "item") }),
121
121
  className: "cursor-pointer ml-auto text-status-error-text transition-colors hover:text-status-error-text-emphasis",
122
122
  children: /* @__PURE__ */ c(a, {
123
123
  className: "size-4",
@@ -129,7 +129,7 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
129
129
  className: "mt-2 text-right",
130
130
  children: /* @__PURE__ */ c("span", {
131
131
  className: "font-semibold tabular-nums text-text-primary",
132
- children: e(t.subtotal)
132
+ children: e(t.subtotal, h)
133
133
  })
134
134
  })
135
135
  ]
@@ -146,30 +146,30 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
146
146
  className: "flex justify-between text-sm",
147
147
  children: [/* @__PURE__ */ c("span", {
148
148
  className: "text-text-muted",
149
- children: b("cart.subtotal", "Subtotal")
149
+ children: x("cart.subtotal", "Subtotal")
150
150
  }), /* @__PURE__ */ c("span", {
151
151
  className: "font-medium tabular-nums text-text-primary",
152
- children: e(h)
152
+ children: e(g, h)
153
153
  })]
154
154
  }),
155
155
  /* @__PURE__ */ l("div", {
156
156
  className: "flex justify-between text-sm",
157
157
  children: [/* @__PURE__ */ c("span", {
158
158
  className: "text-text-muted",
159
- children: b("cart.tax", "Tax")
159
+ children: x("cart.tax", "Tax")
160
160
  }), /* @__PURE__ */ c("span", {
161
161
  className: "font-medium tabular-nums text-text-primary",
162
- children: e(g)
162
+ children: e(_, h)
163
163
  })]
164
164
  }),
165
165
  /* @__PURE__ */ l("div", {
166
166
  className: "flex justify-between border-t border-border-seam pt-2",
167
167
  children: [/* @__PURE__ */ c("span", {
168
168
  className: "font-semibold text-text-primary",
169
- children: b("cart.total", "Total")
169
+ children: x("cart.total", "Total")
170
170
  }), /* @__PURE__ */ c("span", {
171
171
  className: "text-lg font-bold tabular-nums text-text-primary",
172
- children: e(_)
172
+ children: e(v, h)
173
173
  })]
174
174
  })
175
175
  ]
@@ -177,7 +177,7 @@ var u = ({ isOpen: u, onClose: d, onCheckout: f, cartItems: p, itemCount: m, sub
177
177
  type: "button",
178
178
  onClick: f,
179
179
  className: "cursor-pointer mt-4 w-full rounded-lg bg-action-primary-bg py-3 font-bold text-action-primary-text shadow-elevation-1 transition-[opacity,box-shadow] hover:opacity-90 hover:shadow-[var(--shadow-pop)]",
180
- children: b("cart.checkout", "Proceed to Checkout")
180
+ children: x("cart.checkout", "Proceed to Checkout")
181
181
  })]
182
182
  })
183
183
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"CartDrawer.js","names":[],"sources":["../../../src/components/cart/CartDrawer.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { X, ShoppingCart, Trash2, Plus, Minus } from 'lucide-react';\nimport { formatPrice } from '../../utils';\nimport { useTr } from '../../shared/hooks/useTr';\n\n/**\n * Props for CartDrawer\n */\ninterface CartDrawerProps {\n isOpen: boolean;\n onClose: () => void;\n onCheckout: () => void;\n cartItems: Array<{\n id: string;\n quantity: number;\n subtotal: number;\n productName?: string;\n productIcon?: string;\n variantName?: string;\n product?: { icon?: string; name?: string };\n }>;\n itemCount: number;\n subtotal: number;\n tax: number;\n total: number;\n updateQuantity: (cartItemId: string, quantity: number) => Promise<void>;\n removeProduct: (cartItemId: string) => Promise<void>;\n}\n\n/**\n * CartDrawer component\n *\n * Sliding drawer for cart management\n */\nexport const CartDrawer: FC<CartDrawerProps> = ({\n isOpen,\n onClose,\n onCheckout,\n cartItems,\n itemCount,\n subtotal,\n tax,\n total,\n updateQuantity,\n removeProduct,\n}) => {\n const tr = useTr();\n if (!isOpen) return null;\n\n return (\n <>\n {/* Backdrop */}\n <button\n type=\"button\"\n aria-label={tr('cart.closeCart', 'Close cart')}\n className=\"fixed inset-0 z-40 bg-bg-overlay/50 transition-opacity\"\n onClick={onClose}\n />\n\n {/* Drawer */}\n <div className=\"fixed right-0 top-0 z-50 size-full sm:max-w-md bg-bg-surface shadow-xl\">\n <div className=\"flex h-full flex-col\">\n {/* Header */}\n <div className=\"flex items-center justify-between border-b border-border-seam px-4 sm:px-6 py-4\">\n <div className=\"flex items-center gap-2\">\n <ShoppingCart className=\"size-5 text-text-primary\" />\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tr('cart.title', 'Shopping Cart')}\n </h2>\n {itemCount > 0 && (\n <span className=\"rounded-full bg-bg-accent px-2 py-0.5 text-xs font-medium tabular-nums text-text-link\">\n {itemCount}\n </span>\n )}\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n aria-label={tr('cart.closeCart', 'Close cart')}\n className=\"cursor-pointer rounded-lg p-2 text-text-muted transition-colors hover:bg-bg-sunken hover:text-text-primary\"\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n {/* Cart Items */}\n <div className=\"flex-1 overflow-y-auto px-4 sm:px-6 py-4\">\n {cartItems.length === 0 ? (\n <output\n aria-label={tr('cart.empty', 'Your cart is empty')}\n className=\"flex h-full flex-col items-center justify-center text-center\"\n >\n <ShoppingCart className=\"mb-4 size-16 text-text-muted\" aria-hidden=\"true\" />\n <h3 className=\"mb-2 text-lg font-semibold text-text-primary\">\n {tr('cart.empty', 'Your cart is empty')}\n </h3>\n <p className=\"text-sm text-text-muted\">\n {tr('cart.emptyHint', 'Start shopping to add items to your cart')}\n </p>\n </output>\n ) : (\n <div className=\"space-y-4\">\n {cartItems.map((item) => (\n <div\n key={item.id}\n className=\"flex gap-4 rounded-lg border border-border-seam bg-bg-surface p-4 transition-[box-shadow,border-color] hover:border-border-strong hover:shadow-[var(--shadow-pop)]\"\n >\n {/* Product Image */}\n <div className=\"size-20 flex-shrink-0 overflow-hidden rounded bg-bg-sunken\">\n {item.productIcon || item.product?.icon ? (\n <img\n src={item.productIcon || item.product?.icon}\n alt={item.productName || item.product?.name}\n className=\"size-full object-cover\"\n />\n ) : (\n <div className=\"flex size-full items-center justify-center\">\n <ShoppingCart className=\"size-8 text-text-muted\" />\n </div>\n )}\n </div>\n\n {/* Product Info */}\n <div className=\"flex flex-1 flex-col\">\n <h4 className=\"mb-1 font-semibold text-text-primary\">\n {item.productName || item.product?.name || tr('common.product', 'Product')}\n </h4>\n {item.variantName && (\n <p className=\"mb-2 text-xs text-text-muted\">{item.variantName}</p>\n )}\n\n {/* Quantity Controls */}\n <div className=\"flex items-center gap-3\">\n <div className=\"flex items-center rounded border border-border-default\">\n <button\n type=\"button\"\n onClick={() => updateQuantity(item.id, item.quantity - 1)}\n aria-label={tr(\n 'cart.decreaseQuantity',\n 'Decrease quantity of {{name}}',\n {\n name:\n item.productName ||\n item.product?.name ||\n tr('common.item', 'item'),\n }\n )}\n className=\"cursor-pointer p-1.5 transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-50\"\n disabled={item.quantity <= 1}\n >\n <Minus className=\"size-4\" aria-hidden=\"true\" />\n </button>\n <span\n className=\"min-w-[2rem] text-center text-sm font-medium\"\n aria-label={tr('cart.quantity', 'Quantity: {{quantity}}', {\n quantity: item.quantity,\n })}\n >\n {item.quantity}\n </span>\n <button\n type=\"button\"\n onClick={() => updateQuantity(item.id, item.quantity + 1)}\n aria-label={tr(\n 'cart.increaseQuantity',\n 'Increase quantity of {{name}}',\n {\n name:\n item.productName ||\n item.product?.name ||\n tr('common.item', 'item'),\n }\n )}\n className=\"cursor-pointer p-1.5 transition-colors hover:bg-bg-sunken\"\n >\n <Plus className=\"size-4\" aria-hidden=\"true\" />\n </button>\n </div>\n\n <button\n type=\"button\"\n onClick={() => removeProduct(item.id)}\n aria-label={tr('cart.removeItem', 'Remove {{name}} from cart', {\n name:\n item.productName || item.product?.name || tr('common.item', 'item'),\n })}\n className=\"cursor-pointer ml-auto text-status-error-text transition-colors hover:text-status-error-text-emphasis\"\n >\n <Trash2 className=\"size-4\" aria-hidden=\"true\" />\n </button>\n </div>\n\n {/* Price */}\n <div className=\"mt-2 text-right\">\n <span className=\"font-semibold tabular-nums text-text-primary\">\n {formatPrice(item.subtotal)}\n </span>\n </div>\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Footer with Summary */}\n {cartItems.length > 0 && (\n <div className=\"border-t border-border-seam bg-accent-wash px-4 sm:px-6 py-4\">\n <div className=\"space-y-2\">\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-muted\">{tr('cart.subtotal', 'Subtotal')}</span>\n <span className=\"font-medium tabular-nums text-text-primary\">\n {formatPrice(subtotal)}\n </span>\n </div>\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-muted\">{tr('cart.tax', 'Tax')}</span>\n <span className=\"font-medium tabular-nums text-text-primary\">\n {formatPrice(tax)}\n </span>\n </div>\n <div className=\"flex justify-between border-t border-border-seam pt-2\">\n <span className=\"font-semibold text-text-primary\">\n {tr('cart.total', 'Total')}\n </span>\n <span className=\"text-lg font-bold tabular-nums text-text-primary\">\n {formatPrice(total)}\n </span>\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={onCheckout}\n className=\"cursor-pointer mt-4 w-full rounded-lg bg-action-primary-bg py-3 font-bold text-action-primary-text shadow-elevation-1 transition-[opacity,box-shadow] hover:opacity-90 hover:shadow-[var(--shadow-pop)]\"\n >\n {tr('cart.checkout', 'Proceed to Checkout')}\n </button>\n </div>\n )}\n </div>\n </div>\n </>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"CartDrawer.js","names":[],"sources":["../../../src/components/cart/CartDrawer.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { X, ShoppingCart, Trash2, Plus, Minus } from 'lucide-react';\nimport { formatPrice } from '../../utils';\nimport { useTr } from '../../shared/hooks/useTr';\n\n/**\n * Props for CartDrawer\n */\ninterface CartDrawerProps {\n isOpen: boolean;\n onClose: () => void;\n onCheckout: () => void;\n cartItems: Array<{\n id: string;\n quantity: number;\n subtotal: number;\n productName?: string;\n productIcon?: string;\n variantName?: string;\n product?: { icon?: string; name?: string };\n }>;\n itemCount: number;\n /** Cart-wide currency — see useBackendCart.ts's Cart type (one currency per cart). */\n currency: string;\n subtotal: number;\n tax: number;\n total: number;\n updateQuantity: (cartItemId: string, quantity: number) => Promise<void>;\n removeProduct: (cartItemId: string) => Promise<void>;\n}\n\n/**\n * CartDrawer component\n *\n * Sliding drawer for cart management\n */\nexport const CartDrawer: FC<CartDrawerProps> = ({\n isOpen,\n onClose,\n onCheckout,\n cartItems,\n itemCount,\n currency,\n subtotal,\n tax,\n total,\n updateQuantity,\n removeProduct,\n}) => {\n const tr = useTr();\n if (!isOpen) return null;\n\n return (\n <>\n {/* Backdrop */}\n <button\n type=\"button\"\n aria-label={tr('cart.closeCart', 'Close cart')}\n className=\"fixed inset-0 z-40 bg-bg-overlay/50 transition-opacity\"\n onClick={onClose}\n />\n\n {/* Drawer */}\n <div className=\"fixed right-0 top-0 z-50 size-full sm:max-w-md bg-bg-surface shadow-xl\">\n <div className=\"flex h-full flex-col\">\n {/* Header */}\n <div className=\"flex items-center justify-between border-b border-border-seam px-4 sm:px-6 py-4\">\n <div className=\"flex items-center gap-2\">\n <ShoppingCart className=\"size-5 text-text-primary\" />\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tr('cart.title', 'Shopping Cart')}\n </h2>\n {itemCount > 0 && (\n <span className=\"rounded-full bg-bg-accent px-2 py-0.5 text-xs font-medium tabular-nums text-text-link\">\n {itemCount}\n </span>\n )}\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n aria-label={tr('cart.closeCart', 'Close cart')}\n className=\"cursor-pointer rounded-lg p-2 text-text-muted transition-colors hover:bg-bg-sunken hover:text-text-primary\"\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n {/* Cart Items */}\n <div className=\"flex-1 overflow-y-auto px-4 sm:px-6 py-4\">\n {cartItems.length === 0 ? (\n <output\n aria-label={tr('cart.empty', 'Your cart is empty')}\n className=\"flex h-full flex-col items-center justify-center text-center\"\n >\n <ShoppingCart className=\"mb-4 size-16 text-text-muted\" aria-hidden=\"true\" />\n <h3 className=\"mb-2 text-lg font-semibold text-text-primary\">\n {tr('cart.empty', 'Your cart is empty')}\n </h3>\n <p className=\"text-sm text-text-muted\">\n {tr('cart.emptyHint', 'Start shopping to add items to your cart')}\n </p>\n </output>\n ) : (\n <div className=\"space-y-4\">\n {cartItems.map((item) => (\n <div\n key={item.id}\n className=\"flex gap-4 rounded-lg border border-border-seam bg-bg-surface p-4 transition-[box-shadow,border-color] hover:border-border-strong hover:shadow-[var(--shadow-pop)]\"\n >\n {/* Product Image */}\n <div className=\"size-20 flex-shrink-0 overflow-hidden rounded bg-bg-sunken\">\n {item.productIcon || item.product?.icon ? (\n <img\n src={item.productIcon || item.product?.icon}\n alt={item.productName || item.product?.name}\n className=\"size-full object-cover\"\n />\n ) : (\n <div className=\"flex size-full items-center justify-center\">\n <ShoppingCart className=\"size-8 text-text-muted\" />\n </div>\n )}\n </div>\n\n {/* Product Info */}\n <div className=\"flex flex-1 flex-col\">\n <h4 className=\"mb-1 font-semibold text-text-primary\">\n {item.productName || item.product?.name || tr('common.product', 'Product')}\n </h4>\n {item.variantName && (\n <p className=\"mb-2 text-xs text-text-muted\">{item.variantName}</p>\n )}\n\n {/* Quantity Controls */}\n <div className=\"flex items-center gap-3\">\n <div className=\"flex items-center rounded border border-border-default\">\n <button\n type=\"button\"\n onClick={() => updateQuantity(item.id, item.quantity - 1)}\n aria-label={tr(\n 'cart.decreaseQuantity',\n 'Decrease quantity of {{name}}',\n {\n name:\n item.productName ||\n item.product?.name ||\n tr('common.item', 'item'),\n }\n )}\n className=\"cursor-pointer p-1.5 transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-50\"\n disabled={item.quantity <= 1}\n >\n <Minus className=\"size-4\" aria-hidden=\"true\" />\n </button>\n <span\n className=\"min-w-[2rem] text-center text-sm font-medium\"\n aria-label={tr('cart.quantity', 'Quantity: {{quantity}}', {\n quantity: item.quantity,\n })}\n >\n {item.quantity}\n </span>\n <button\n type=\"button\"\n onClick={() => updateQuantity(item.id, item.quantity + 1)}\n aria-label={tr(\n 'cart.increaseQuantity',\n 'Increase quantity of {{name}}',\n {\n name:\n item.productName ||\n item.product?.name ||\n tr('common.item', 'item'),\n }\n )}\n className=\"cursor-pointer p-1.5 transition-colors hover:bg-bg-sunken\"\n >\n <Plus className=\"size-4\" aria-hidden=\"true\" />\n </button>\n </div>\n\n <button\n type=\"button\"\n onClick={() => removeProduct(item.id)}\n aria-label={tr('cart.removeItem', 'Remove {{name}} from cart', {\n name:\n item.productName || item.product?.name || tr('common.item', 'item'),\n })}\n className=\"cursor-pointer ml-auto text-status-error-text transition-colors hover:text-status-error-text-emphasis\"\n >\n <Trash2 className=\"size-4\" aria-hidden=\"true\" />\n </button>\n </div>\n\n {/* Price */}\n <div className=\"mt-2 text-right\">\n <span className=\"font-semibold tabular-nums text-text-primary\">\n {formatPrice(item.subtotal, currency)}\n </span>\n </div>\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Footer with Summary */}\n {cartItems.length > 0 && (\n <div className=\"border-t border-border-seam bg-accent-wash px-4 sm:px-6 py-4\">\n <div className=\"space-y-2\">\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-muted\">{tr('cart.subtotal', 'Subtotal')}</span>\n <span className=\"font-medium tabular-nums text-text-primary\">\n {formatPrice(subtotal, currency)}\n </span>\n </div>\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-muted\">{tr('cart.tax', 'Tax')}</span>\n <span className=\"font-medium tabular-nums text-text-primary\">\n {formatPrice(tax, currency)}\n </span>\n </div>\n <div className=\"flex justify-between border-t border-border-seam pt-2\">\n <span className=\"font-semibold text-text-primary\">\n {tr('cart.total', 'Total')}\n </span>\n <span className=\"text-lg font-bold tabular-nums text-text-primary\">\n {formatPrice(total, currency)}\n </span>\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={onCheckout}\n className=\"cursor-pointer mt-4 w-full rounded-lg bg-action-primary-bg py-3 font-bold text-action-primary-text shadow-elevation-1 transition-[opacity,box-shadow] hover:opacity-90 hover:shadow-[var(--shadow-pop)]\"\n >\n {tr('cart.checkout', 'Proceed to Checkout')}\n </button>\n </div>\n )}\n </div>\n </div>\n </>\n );\n};\n"],"mappings":"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"}
@@ -892,6 +892,7 @@ export type BrowseStoreQuery = {
892
892
  rating?: number | null;
893
893
  reviewCount: number;
894
894
  downloads: number;
895
+ purchaseCount: number;
895
896
  featured: boolean;
896
897
  category?: string | null;
897
898
  tags: Array<string>;
@@ -1221,6 +1222,7 @@ export type HomeGroupedProductsQuery = {
1221
1222
  rating?: number | null;
1222
1223
  reviewCount: number;
1223
1224
  downloads: number;
1225
+ purchaseCount: number;
1224
1226
  featured: boolean;
1225
1227
  category?: string | null;
1226
1228
  tags: Array<string>;
@@ -1250,6 +1252,7 @@ export type HomeGroupedProductsQuery = {
1250
1252
  rating?: number | null;
1251
1253
  reviewCount: number;
1252
1254
  downloads: number;
1255
+ purchaseCount: number;
1253
1256
  featured: boolean;
1254
1257
  category?: string | null;
1255
1258
  tags: Array<string>;
@@ -1279,6 +1282,7 @@ export type HomeGroupedProductsQuery = {
1279
1282
  rating?: number | null;
1280
1283
  reviewCount: number;
1281
1284
  downloads: number;
1285
+ purchaseCount: number;
1282
1286
  featured: boolean;
1283
1287
  category?: string | null;
1284
1288
  tags: Array<string>;
@@ -1308,6 +1312,7 @@ export type HomeGroupedProductsQuery = {
1308
1312
  rating?: number | null;
1309
1313
  reviewCount: number;
1310
1314
  downloads: number;
1315
+ purchaseCount: number;
1311
1316
  featured: boolean;
1312
1317
  category?: string | null;
1313
1318
  tags: Array<string>;
@@ -1353,6 +1358,7 @@ export type StoreProductDetailsQuery = {
1353
1358
  rating?: number | null;
1354
1359
  reviewCount: number;
1355
1360
  downloads: number;
1361
+ purchaseCount: number;
1356
1362
  viewCount: number;
1357
1363
  featured: boolean;
1358
1364
  category?: string | null;
@@ -1422,6 +1428,7 @@ export type StoreProductDetailsQuery = {
1422
1428
  rating?: number | null;
1423
1429
  reviewCount: number;
1424
1430
  downloads: number;
1431
+ purchaseCount: number;
1425
1432
  price: number;
1426
1433
  pricingModel: Types.PricingModel;
1427
1434
  currency: string;
@@ -1077,6 +1077,7 @@ var V = t`
1077
1077
  rating
1078
1078
  reviewCount
1079
1079
  downloads
1080
+ purchaseCount
1080
1081
  featured
1081
1082
  category
1082
1083
  tags
@@ -1509,6 +1510,7 @@ var J = t`
1509
1510
  rating
1510
1511
  reviewCount
1511
1512
  downloads
1513
+ purchaseCount
1512
1514
  featured
1513
1515
  category
1514
1516
  tags
@@ -1536,6 +1538,7 @@ var J = t`
1536
1538
  rating
1537
1539
  reviewCount
1538
1540
  downloads
1541
+ purchaseCount
1539
1542
  featured
1540
1543
  category
1541
1544
  tags
@@ -1563,6 +1566,7 @@ var J = t`
1563
1566
  rating
1564
1567
  reviewCount
1565
1568
  downloads
1569
+ purchaseCount
1566
1570
  featured
1567
1571
  category
1568
1572
  tags
@@ -1590,6 +1594,7 @@ var J = t`
1590
1594
  rating
1591
1595
  reviewCount
1592
1596
  downloads
1597
+ purchaseCount
1593
1598
  featured
1594
1599
  category
1595
1600
  tags
@@ -1649,6 +1654,7 @@ var Y = t`
1649
1654
  rating
1650
1655
  reviewCount
1651
1656
  downloads
1657
+ purchaseCount
1652
1658
  viewCount
1653
1659
  featured
1654
1660
  category
@@ -1713,6 +1719,7 @@ var Y = t`
1713
1719
  rating
1714
1720
  reviewCount
1715
1721
  downloads
1722
+ purchaseCount
1716
1723
  price
1717
1724
  pricingModel
1718
1725
  currency