@burdenoff/microfe-store 2026.830.1 → 2026.830.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.
@@ -1,186 +1,190 @@
1
1
  import { formatPrice as e } from "../../utils/index.js";
2
- import { Minus as t, Plus as n, ShoppingCart as r, Trash2 as i, X as a } from "lucide-react";
3
- import { Fragment as o, jsx as s, jsxs as c } from "react/jsx-runtime";
2
+ import { useTr as t } from "../../shared/hooks/useTr.js";
3
+ import { Minus as n, Plus as r, ShoppingCart as i, Trash2 as a, X as o } from "lucide-react";
4
+ import { Fragment as s, jsx as c, jsxs as l } from "react/jsx-runtime";
4
5
  //#region src/components/cart/CartDrawer.tsx
5
- var l = ({ isOpen: l, onClose: u, onCheckout: d, cartItems: f, itemCount: p, subtotal: m, tax: h, total: g, updateQuantity: _, removeProduct: v }) => l ? /* @__PURE__ */ c(o, { children: [/* @__PURE__ */ s("button", {
6
- type: "button",
7
- "aria-label": "Close cart",
8
- className: "fixed inset-0 z-40 bg-bg-overlay/50 transition-opacity",
9
- onClick: u
10
- }), /* @__PURE__ */ s("div", {
11
- className: "fixed right-0 top-0 z-50 size-full sm:max-w-md bg-bg-surface shadow-xl",
12
- children: /* @__PURE__ */ c("div", {
13
- className: "flex h-full flex-col",
14
- children: [
15
- /* @__PURE__ */ c("div", {
16
- className: "flex items-center justify-between border-b border-border-seam px-4 sm:px-6 py-4",
17
- children: [/* @__PURE__ */ c("div", {
18
- className: "flex items-center gap-2",
19
- children: [
20
- /* @__PURE__ */ s(r, { className: "size-5 text-text-primary" }),
21
- /* @__PURE__ */ s("h2", {
22
- className: "text-lg font-semibold text-text-primary",
23
- children: "Shopping Cart"
24
- }),
25
- p > 0 && /* @__PURE__ */ s("span", {
26
- className: "rounded-full bg-bg-accent px-2 py-0.5 text-xs font-medium tabular-nums text-text-link",
27
- children: p
28
- })
29
- ]
30
- }), /* @__PURE__ */ s("button", {
31
- type: "button",
32
- onClick: u,
33
- "aria-label": "Close cart",
34
- className: "cursor-pointer rounded-lg p-2 text-text-muted transition-colors hover:bg-bg-sunken hover:text-text-primary",
35
- children: /* @__PURE__ */ s(a, { className: "size-5" })
36
- })]
37
- }),
38
- /* @__PURE__ */ s("div", {
39
- className: "flex-1 overflow-y-auto px-4 sm:px-6 py-4",
40
- children: f.length === 0 ? /* @__PURE__ */ c("output", {
41
- "aria-label": "Your cart is empty",
42
- className: "flex h-full flex-col items-center justify-center text-center",
43
- children: [
44
- /* @__PURE__ */ s(r, {
45
- className: "mb-4 size-16 text-text-muted",
46
- "aria-hidden": "true"
47
- }),
48
- /* @__PURE__ */ s("h3", {
49
- className: "mb-2 text-lg font-semibold text-text-primary",
50
- children: "Your cart is empty"
51
- }),
52
- /* @__PURE__ */ s("p", {
53
- className: "text-sm text-text-muted",
54
- children: "Start shopping to add items to your cart"
55
- })
56
- ]
57
- }) : /* @__PURE__ */ s("div", {
58
- className: "space-y-4",
59
- children: f.map((a) => /* @__PURE__ */ c("div", {
60
- 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)]",
61
- children: [/* @__PURE__ */ s("div", {
62
- className: "size-20 flex-shrink-0 overflow-hidden rounded bg-bg-sunken",
63
- children: a.productIcon || a.product?.icon ? /* @__PURE__ */ s("img", {
64
- src: a.productIcon || a.product?.icon,
65
- alt: a.productName || a.product?.name,
66
- className: "size-full object-cover"
67
- }) : /* @__PURE__ */ s("div", {
68
- className: "flex size-full items-center justify-center",
69
- children: /* @__PURE__ */ s(r, { className: "size-8 text-text-muted" })
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();
8
+ return u ? /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ c("button", {
9
+ type: "button",
10
+ "aria-label": b("cart.closeCart", "Close cart"),
11
+ className: "fixed inset-0 z-40 bg-bg-overlay/50 transition-opacity",
12
+ onClick: d
13
+ }), /* @__PURE__ */ c("div", {
14
+ className: "fixed right-0 top-0 z-50 size-full sm:max-w-md bg-bg-surface shadow-xl",
15
+ children: /* @__PURE__ */ l("div", {
16
+ className: "flex h-full flex-col",
17
+ children: [
18
+ /* @__PURE__ */ l("div", {
19
+ className: "flex items-center justify-between border-b border-border-seam px-4 sm:px-6 py-4",
20
+ children: [/* @__PURE__ */ l("div", {
21
+ className: "flex items-center gap-2",
22
+ children: [
23
+ /* @__PURE__ */ c(i, { className: "size-5 text-text-primary" }),
24
+ /* @__PURE__ */ c("h2", {
25
+ className: "text-lg font-semibold text-text-primary",
26
+ children: b("cart.title", "Shopping Cart")
27
+ }),
28
+ m > 0 && /* @__PURE__ */ c("span", {
29
+ className: "rounded-full bg-bg-accent px-2 py-0.5 text-xs font-medium tabular-nums text-text-link",
30
+ children: m
70
31
  })
71
- }), /* @__PURE__ */ c("div", {
72
- className: "flex flex-1 flex-col",
73
- children: [
74
- /* @__PURE__ */ s("h4", {
75
- className: "mb-1 font-semibold text-text-primary",
76
- children: a.productName || a.product?.name || "Product"
77
- }),
78
- a.variantName && /* @__PURE__ */ s("p", {
79
- className: "mb-2 text-xs text-text-muted",
80
- children: a.variantName
81
- }),
82
- /* @__PURE__ */ c("div", {
83
- className: "flex items-center gap-3",
84
- children: [/* @__PURE__ */ c("div", {
85
- className: "flex items-center rounded border border-border-default",
86
- children: [
87
- /* @__PURE__ */ s("button", {
88
- type: "button",
89
- onClick: () => _(a.id, a.quantity - 1),
90
- "aria-label": `Decrease quantity of ${a.productName || a.product?.name || "item"}`,
91
- className: "cursor-pointer p-1.5 transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-50",
92
- disabled: a.quantity <= 1,
93
- children: /* @__PURE__ */ s(t, {
94
- className: "size-4",
95
- "aria-hidden": "true"
96
- })
97
- }),
98
- /* @__PURE__ */ s("span", {
99
- className: "min-w-[2rem] text-center text-sm font-medium",
100
- "aria-label": `Quantity: ${a.quantity}`,
101
- children: a.quantity
102
- }),
103
- /* @__PURE__ */ s("button", {
104
- type: "button",
105
- onClick: () => _(a.id, a.quantity + 1),
106
- "aria-label": `Increase quantity of ${a.productName || a.product?.name || "item"}`,
107
- className: "cursor-pointer p-1.5 transition-colors hover:bg-bg-sunken",
108
- children: /* @__PURE__ */ s(n, {
109
- className: "size-4",
110
- "aria-hidden": "true"
32
+ ]
33
+ }), /* @__PURE__ */ c("button", {
34
+ type: "button",
35
+ onClick: d,
36
+ "aria-label": b("cart.closeCart", "Close cart"),
37
+ className: "cursor-pointer rounded-lg p-2 text-text-muted transition-colors hover:bg-bg-sunken hover:text-text-primary",
38
+ children: /* @__PURE__ */ c(o, { className: "size-5" })
39
+ })]
40
+ }),
41
+ /* @__PURE__ */ c("div", {
42
+ className: "flex-1 overflow-y-auto px-4 sm:px-6 py-4",
43
+ children: p.length === 0 ? /* @__PURE__ */ l("output", {
44
+ "aria-label": b("cart.empty", "Your cart is empty"),
45
+ className: "flex h-full flex-col items-center justify-center text-center",
46
+ children: [
47
+ /* @__PURE__ */ c(i, {
48
+ className: "mb-4 size-16 text-text-muted",
49
+ "aria-hidden": "true"
50
+ }),
51
+ /* @__PURE__ */ c("h3", {
52
+ className: "mb-2 text-lg font-semibold text-text-primary",
53
+ children: b("cart.empty", "Your cart is empty")
54
+ }),
55
+ /* @__PURE__ */ c("p", {
56
+ className: "text-sm text-text-muted",
57
+ children: b("cart.emptyHint", "Start shopping to add items to your cart")
58
+ })
59
+ ]
60
+ }) : /* @__PURE__ */ c("div", {
61
+ className: "space-y-4",
62
+ children: p.map((t) => /* @__PURE__ */ l("div", {
63
+ 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)]",
64
+ children: [/* @__PURE__ */ c("div", {
65
+ className: "size-20 flex-shrink-0 overflow-hidden rounded bg-bg-sunken",
66
+ children: t.productIcon || t.product?.icon ? /* @__PURE__ */ c("img", {
67
+ src: t.productIcon || t.product?.icon,
68
+ alt: t.productName || t.product?.name,
69
+ className: "size-full object-cover"
70
+ }) : /* @__PURE__ */ c("div", {
71
+ className: "flex size-full items-center justify-center",
72
+ children: /* @__PURE__ */ c(i, { className: "size-8 text-text-muted" })
73
+ })
74
+ }), /* @__PURE__ */ l("div", {
75
+ className: "flex flex-1 flex-col",
76
+ children: [
77
+ /* @__PURE__ */ c("h4", {
78
+ className: "mb-1 font-semibold text-text-primary",
79
+ children: t.productName || t.product?.name || b("common.product", "Product")
80
+ }),
81
+ t.variantName && /* @__PURE__ */ c("p", {
82
+ className: "mb-2 text-xs text-text-muted",
83
+ children: t.variantName
84
+ }),
85
+ /* @__PURE__ */ l("div", {
86
+ className: "flex items-center gap-3",
87
+ children: [/* @__PURE__ */ l("div", {
88
+ className: "flex items-center rounded border border-border-default",
89
+ children: [
90
+ /* @__PURE__ */ c("button", {
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") }),
94
+ className: "cursor-pointer p-1.5 transition-colors hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-50",
95
+ disabled: t.quantity <= 1,
96
+ children: /* @__PURE__ */ c(n, {
97
+ className: "size-4",
98
+ "aria-hidden": "true"
99
+ })
100
+ }),
101
+ /* @__PURE__ */ c("span", {
102
+ className: "min-w-[2rem] text-center text-sm font-medium",
103
+ "aria-label": b("cart.quantity", "Quantity: {{quantity}}", { quantity: t.quantity }),
104
+ children: t.quantity
105
+ }),
106
+ /* @__PURE__ */ c("button", {
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") }),
110
+ className: "cursor-pointer p-1.5 transition-colors hover:bg-bg-sunken",
111
+ children: /* @__PURE__ */ c(r, {
112
+ className: "size-4",
113
+ "aria-hidden": "true"
114
+ })
111
115
  })
116
+ ]
117
+ }), /* @__PURE__ */ c("button", {
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") }),
121
+ className: "cursor-pointer ml-auto text-status-error-text transition-colors hover:text-status-error-text-emphasis",
122
+ children: /* @__PURE__ */ c(a, {
123
+ className: "size-4",
124
+ "aria-hidden": "true"
112
125
  })
113
- ]
114
- }), /* @__PURE__ */ s("button", {
115
- type: "button",
116
- onClick: () => v(a.id),
117
- "aria-label": `Remove ${a.productName || a.product?.name || "item"} from cart`,
118
- className: "cursor-pointer ml-auto text-status-error-text transition-colors hover:text-status-error-text-emphasis",
119
- children: /* @__PURE__ */ s(i, {
120
- className: "size-4",
121
- "aria-hidden": "true"
126
+ })]
127
+ }),
128
+ /* @__PURE__ */ c("div", {
129
+ className: "mt-2 text-right",
130
+ children: /* @__PURE__ */ c("span", {
131
+ className: "font-semibold tabular-nums text-text-primary",
132
+ children: e(t.subtotal)
122
133
  })
123
- })]
124
- }),
125
- /* @__PURE__ */ s("div", {
126
- className: "mt-2 text-right",
127
- children: /* @__PURE__ */ s("span", {
128
- className: "font-semibold tabular-nums text-text-primary",
129
- children: e(a.subtotal)
130
134
  })
131
- })
132
- ]
133
- })]
134
- }, a.id))
135
- })
136
- }),
137
- f.length > 0 && /* @__PURE__ */ c("div", {
138
- className: "border-t border-border-seam bg-accent-wash px-4 sm:px-6 py-4",
139
- children: [/* @__PURE__ */ c("div", {
140
- className: "space-y-2",
141
- children: [
142
- /* @__PURE__ */ c("div", {
143
- className: "flex justify-between text-sm",
144
- children: [/* @__PURE__ */ s("span", {
145
- className: "text-text-muted",
146
- children: "Subtotal"
147
- }), /* @__PURE__ */ s("span", {
148
- className: "font-medium tabular-nums text-text-primary",
149
- children: e(m)
135
+ ]
150
136
  })]
151
- }),
152
- /* @__PURE__ */ c("div", {
153
- className: "flex justify-between text-sm",
154
- children: [/* @__PURE__ */ s("span", {
155
- className: "text-text-muted",
156
- children: "Tax"
157
- }), /* @__PURE__ */ s("span", {
158
- className: "font-medium tabular-nums text-text-primary",
159
- children: e(h)
160
- })]
161
- }),
162
- /* @__PURE__ */ c("div", {
163
- className: "flex justify-between border-t border-border-seam pt-2",
164
- children: [/* @__PURE__ */ s("span", {
165
- className: "font-semibold text-text-primary",
166
- children: "Total"
167
- }), /* @__PURE__ */ s("span", {
168
- className: "text-lg font-bold tabular-nums text-text-primary",
169
- children: e(g)
170
- })]
171
- })
172
- ]
173
- }), /* @__PURE__ */ s("button", {
174
- type: "button",
175
- onClick: d,
176
- 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)]",
177
- children: "Proceed to Checkout"
178
- })]
179
- })
180
- ]
181
- })
182
- })] }) : null;
137
+ }, t.id))
138
+ })
139
+ }),
140
+ p.length > 0 && /* @__PURE__ */ l("div", {
141
+ className: "border-t border-border-seam bg-accent-wash px-4 sm:px-6 py-4",
142
+ children: [/* @__PURE__ */ l("div", {
143
+ className: "space-y-2",
144
+ children: [
145
+ /* @__PURE__ */ l("div", {
146
+ className: "flex justify-between text-sm",
147
+ children: [/* @__PURE__ */ c("span", {
148
+ className: "text-text-muted",
149
+ children: b("cart.subtotal", "Subtotal")
150
+ }), /* @__PURE__ */ c("span", {
151
+ className: "font-medium tabular-nums text-text-primary",
152
+ children: e(h)
153
+ })]
154
+ }),
155
+ /* @__PURE__ */ l("div", {
156
+ className: "flex justify-between text-sm",
157
+ children: [/* @__PURE__ */ c("span", {
158
+ className: "text-text-muted",
159
+ children: b("cart.tax", "Tax")
160
+ }), /* @__PURE__ */ c("span", {
161
+ className: "font-medium tabular-nums text-text-primary",
162
+ children: e(g)
163
+ })]
164
+ }),
165
+ /* @__PURE__ */ l("div", {
166
+ className: "flex justify-between border-t border-border-seam pt-2",
167
+ children: [/* @__PURE__ */ c("span", {
168
+ className: "font-semibold text-text-primary",
169
+ children: b("cart.total", "Total")
170
+ }), /* @__PURE__ */ c("span", {
171
+ className: "text-lg font-bold tabular-nums text-text-primary",
172
+ children: e(_)
173
+ })]
174
+ })
175
+ ]
176
+ }), /* @__PURE__ */ c("button", {
177
+ type: "button",
178
+ onClick: f,
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")
181
+ })]
182
+ })
183
+ ]
184
+ })
185
+ })] }) : null;
186
+ };
183
187
  //#endregion
184
- export { l as CartDrawer };
188
+ export { u as CartDrawer };
185
189
 
186
190
  //# sourceMappingURL=CartDrawer.js.map
@@ -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';\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 if (!isOpen) return null;\n\n return (\n <>\n {/* Backdrop */}\n <button\n type=\"button\"\n aria-label=\"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\">Shopping Cart</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=\"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=\"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\">Your cart is empty</h3>\n <p className=\"text-sm text-text-muted\">Start shopping to add items to your cart</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 || '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={`Decrease quantity of ${item.productName || item.product?.name || 'item'}`}\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={`Quantity: ${item.quantity}`}\n >\n {item.quantity}\n </span>\n <button\n type=\"button\"\n onClick={() => updateQuantity(item.id, item.quantity + 1)}\n aria-label={`Increase quantity of ${item.productName || item.product?.name || 'item'}`}\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={`Remove ${item.productName || item.product?.name || 'item'} from cart`}\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\">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\">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\">Total</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 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 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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"}