@cartbase/storefront 0.18.0 → 0.18.1

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/package.json CHANGED
@@ -1,258 +1,258 @@
1
- {
2
- "name": "@cartbase/storefront",
3
- "version": "0.18.0",
4
- "description": "Storefront SDK + UI component library for Cartbase stores: typed API client, checkout orchestration, cart drawer, product/catalog components, tracking. Source-shipped TypeScript — add it to transpilePackages.",
5
- "license": "MIT",
6
- "repository": {
7
- "type": "git",
8
- "url": "git+https://github.com/Cartbase/cartbase.git",
9
- "directory": "packages/storefront"
10
- },
11
- "type": "module",
12
- "sideEffects": false,
13
- "files": [
14
- "src",
15
- "theme",
16
- "README.md"
17
- ],
18
- "exports": {
19
- ".": "./src/index.ts",
20
- "./api": "./src/api/index.ts",
21
- "./api/http": "./src/api/http.ts",
22
- "./api/types": "./src/api/types.ts",
23
- "./api/products": "./src/api/products.ts",
24
- "./api/collections": "./src/api/collections.ts",
25
- "./api/categories": "./src/api/categories.ts",
26
- "./api/regions": "./src/api/regions.ts",
27
- "./api/store": "./src/api/store.ts",
28
- "./api/carts": "./src/api/carts.ts",
29
- "./api/gift-cards": "./src/api/gift-cards.ts",
30
- "./api/checkout": "./src/api/checkout.ts",
31
- "./api/orders": "./src/api/orders.ts",
32
- "./api/customers": "./src/api/customers.ts",
33
- "./api/auth": "./src/api/auth.ts",
34
- "./api/content": "./src/api/content.ts",
35
- "./api/menus": "./src/api/menus.ts",
36
- "./api/metaobjects": "./src/api/metaobjects.ts",
37
- "./api/reviews": "./src/api/reviews.ts",
38
- "./api/search": "./src/api/search.ts",
39
- "./api/integrations": "./src/api/integrations.ts",
40
- "./api/consent": "./src/api/consent.ts",
41
- "./api/redirects": "./src/api/redirects.ts",
42
- "./theme": "./theme/index.css",
43
- "./theme/tokens.css": "./theme/tokens.css",
44
- "./theme/theme.css": "./theme/theme.css",
45
- "./lib/utils": "./src/lib/utils.ts",
46
- "./lib/money": "./src/lib/money.ts",
47
- "./lib/cart-helpers": "./src/lib/cart-helpers.ts",
48
- "./lib/get-product-price": "./src/lib/get-product-price.ts",
49
- "./lib/get-percentage-diff": "./src/lib/get-percentage-diff.ts",
50
- "./lib/product": "./src/lib/product.ts",
51
- "./lib/sort-products": "./src/lib/sort-products.ts",
52
- "./lib/price": "./src/lib/price.tsx",
53
- "./lib/payment-constants": "./src/lib/payment-constants.ts",
54
- "./lib/country-name": "./src/lib/country-name.ts",
55
- "./lib/store-api-error": "./src/lib/store-api-error.ts",
56
- "./lib/hooks/use-intersection": "./src/lib/hooks/use-intersection.ts",
57
- "./lib/hooks/use-toggle-state": "./src/lib/hooks/use-toggle-state.ts",
58
- "./lib/cookie-names": "./src/lib/cookie-names.ts",
59
- "./lib/media-image": "./src/lib/media-image.tsx",
60
- "./lib/platform": "./src/lib/platform.ts",
61
- "./lib/visitor": "./src/lib/visitor.ts",
62
- "./platform": "./src/platform/index.ts",
63
- "./platform/identity": "./src/platform/identity.ts",
64
- "./platform/metadata": "./src/platform/metadata.ts",
65
- "./platform/platform-init": "./src/platform/platform-init.tsx",
66
- "./primitives/field": "./src/primitives/field.tsx",
67
- "./primitives/select-field": "./src/primitives/select-field.tsx",
68
- "./primitives/ui/accordion": "./src/primitives/ui/accordion.tsx",
69
- "./primitives/ui/button": "./src/primitives/ui/button.tsx",
70
- "./primitives/ui/collapsible": "./src/primitives/ui/collapsible.tsx",
71
- "./primitives/ui/dialog": "./src/primitives/ui/dialog.tsx",
72
- "./primitives/ui/input": "./src/primitives/ui/input.tsx",
73
- "./primitives/ui/label": "./src/primitives/ui/label.tsx",
74
- "./primitives/ui/popover": "./src/primitives/ui/popover.tsx",
75
- "./primitives/ui/select": "./src/primitives/ui/select.tsx",
76
- "./primitives/ui/sheet": "./src/primitives/ui/sheet.tsx",
77
- "./primitives/ui/tabs": "./src/primitives/ui/tabs.tsx",
78
- "./tracking": "./src/tracking/index.ts",
79
- "./tracking/types": "./src/tracking/types.ts",
80
- "./tracking/consent": "./src/tracking/consent.ts",
81
- "./tracking/consent-init": "./src/tracking/consent-init.tsx",
82
- "./tracking/consent-banner": "./src/tracking/consent-banner.tsx",
83
- "./tracking/meta-pixel": "./src/tracking/meta-pixel.tsx",
84
- "./tracking/ga4": "./src/tracking/ga4.tsx",
85
- "./tracking/tiktok-pixel": "./src/tracking/tiktok-pixel.tsx",
86
- "./tracking/ttq": "./src/tracking/ttq.ts",
87
- "./tracking/events": "./src/tracking/events.ts",
88
- "./tracking/storefront-tags": "./src/tracking/storefront-tags.tsx",
89
- "./tracking/track-init": "./src/tracking/track-init.tsx",
90
- "./tracking/track-order-purchase": "./src/tracking/track-order-purchase.tsx",
91
- "./tracking/gtm": "./src/tracking/gtm.tsx",
92
- "./tracking/inline-script": "./src/tracking/inline-script.ts",
93
- "./tracking/google-ads": "./src/tracking/google-ads.ts",
94
- "./tracking/rybbit": "./src/tracking/rybbit.tsx",
95
- "./tracking/rybbit-events": "./src/tracking/rybbit-events.ts",
96
- "./tracking/fbq": "./src/tracking/fbq.ts",
97
- "./tracking/gtag": "./src/tracking/gtag.ts",
98
- "./tracking/attribution": "./src/tracking/attribution.ts",
99
- "./tracking/get-tracking-config": "./src/tracking/get-tracking-config.ts",
100
- "./tracking/use-tracking-config": "./src/tracking/use-tracking-config.ts",
101
- "./tracking/get-tracking-attribution": "./src/tracking/get-tracking-attribution.ts",
102
- "./tracking/use-engagement-time": "./src/tracking/use-engagement-time.ts",
103
- "./tracking/page-views": "./src/tracking/page-views.tsx",
104
- "./tracking/live-heartbeat": "./src/tracking/live-heartbeat.tsx",
105
- "./checkout": "./src/checkout/index.ts",
106
- "./checkout/context": "./src/checkout/context.tsx",
107
- "./checkout/labels": "./src/checkout/labels.ts",
108
- "./checkout/error-message": "./src/checkout/error-message.tsx",
109
- "./checkout/stripe-wrapper": "./src/checkout/stripe-wrapper.tsx",
110
- "./checkout/payment-wrapper": "./src/checkout/payment-wrapper.tsx",
111
- "./checkout/payment-button": "./src/checkout/payment-button.tsx",
112
- "./checkout/econt-office-selector": "./src/checkout/econt-office-selector.tsx",
113
- "./checkout/boxnow-locker-selector": "./src/checkout/boxnow-locker-selector.tsx",
114
- "./checkout/address-select": "./src/checkout/address-select.tsx",
115
- "./checkout/company-details": "./src/checkout/company-details.tsx",
116
- "./checkout/discount-section": "./src/checkout/discount-section.tsx",
117
- "./checkout/gift-card-section": "./src/checkout/gift-card-section.tsx",
118
- "./checkout/line-item-card": "./src/checkout/line-item-card.tsx",
119
- "./checkout/order-summary": "./src/checkout/order-summary.tsx",
120
- "./checkout/address-form": "./src/checkout/address-form.tsx",
121
- "./checkout/shipping-method-list": "./src/checkout/shipping-method-list.tsx",
122
- "./checkout/payment-method-list": "./src/checkout/payment-method-list.tsx",
123
- "./checkout/checkout-client": "./src/checkout/checkout-client.tsx",
124
- "./checkout/use-checkout-orchestration": "./src/checkout/use-checkout-orchestration.ts",
125
- "./checkout/payment-error-copy": "./src/checkout/payment-error-copy.ts",
126
- "./checkout/address-error-copy": "./src/checkout/address-error-copy.ts",
127
- "./checkout/promotion-error-copy": "./src/checkout/promotion-error-copy.ts",
128
- "./cart-drawer": "./src/cart-drawer/index.ts",
129
- "./cart-drawer/context": "./src/cart-drawer/context.tsx",
130
- "./cart-drawer/mutation-queue": "./src/cart-drawer/mutation-queue.ts",
131
- "./cart-drawer/labels": "./src/cart-drawer/labels.ts",
132
- "./cart-drawer/cart-drawer": "./src/cart-drawer/cart-drawer.tsx",
133
- "./cart-drawer/header": "./src/cart-drawer/header.tsx",
134
- "./cart-drawer/promo-banner": "./src/cart-drawer/promo-banner.tsx",
135
- "./cart-drawer/tiered-progress": "./src/cart-drawer/tiered-progress.tsx",
136
- "./cart-drawer/item": "./src/cart-drawer/item/index.tsx",
137
- "./cart-drawer/item/quantity": "./src/cart-drawer/item/quantity.tsx",
138
- "./cart-drawer/item/variant": "./src/cart-drawer/item/variant.tsx",
139
- "./cart-drawer/item/upsell": "./src/cart-drawer/item/upsell.tsx",
140
- "./cart-drawer/free-gift": "./src/cart-drawer/free-gift.tsx",
141
- "./cart-drawer/gift-wrap": "./src/cart-drawer/gift-wrap.tsx",
142
- "./cart-drawer/notes": "./src/cart-drawer/notes.tsx",
143
- "./cart-drawer/rewards-points": "./src/cart-drawer/rewards-points.tsx",
144
- "./cart-drawer/cross-sell-sidebar": "./src/cart-drawer/cross-sell-sidebar.tsx",
145
- "./cart-drawer/cross-sell-carousel": "./src/cart-drawer/cross-sell-carousel.tsx",
146
- "./cart-drawer/summary-breakdown": "./src/cart-drawer/summary-breakdown.tsx",
147
- "./cart-drawer/sticky-footer": "./src/cart-drawer/sticky-footer.tsx",
148
- "./cart-drawer/payment-badges": "./src/cart-drawer/payment-badges.tsx",
149
- "./cart-drawer/continue-shopping": "./src/cart-drawer/continue-shopping.tsx",
150
- "./cart-drawer/empty": "./src/cart-drawer/empty.tsx",
151
- "./cart-drawer/template": "./src/cart-drawer/template.tsx",
152
- "./products": "./src/products/index.ts",
153
- "./products/context": "./src/products/context.tsx",
154
- "./products/labels": "./src/products/labels.ts",
155
- "./products/thumbnail": "./src/products/thumbnail.tsx",
156
- "./products/preview-price": "./src/products/preview-price.tsx",
157
- "./products/product-price": "./src/products/product-price.tsx",
158
- "./products/option-select": "./src/products/option-select.tsx",
159
- "./products/image-gallery": "./src/products/image-gallery.tsx",
160
- "./products/variant-url": "./src/products/variant-url.ts",
161
- "./products/sets": "./src/products/sets.ts",
162
- "./products/use-product-actions": "./src/products/use-product-actions.ts",
163
- "./products/product-actions": "./src/products/product-actions.tsx",
164
- "./products/mobile-actions": "./src/products/mobile-actions.tsx",
165
- "./products/product-tabs": "./src/products/product-tabs.tsx",
166
- "./products/product-specs": "./src/products/product-specs.tsx",
167
- "./products/product-promises": "./src/products/product-promises.tsx",
168
- "./products/product-info": "./src/products/product-info.tsx",
169
- "./products/product-preview": "./src/products/product-preview.tsx",
170
- "./products/related-products": "./src/products/related-products.tsx",
171
- "./products/product-actions-wrapper": "./src/products/product-actions-wrapper.tsx",
172
- "./products/product-template": "./src/products/product-template.tsx",
173
- "./store": "./src/store/index.ts",
174
- "./store/labels": "./src/store/labels.ts",
175
- "./store/pagination": "./src/store/pagination.tsx",
176
- "./store/sort-select": "./src/store/sort-select.tsx",
177
- "./store/paginated-products": "./src/store/paginated-products.tsx",
178
- "./store/skeleton-product-grid": "./src/store/skeleton-product-grid.tsx",
179
- "./store/store-template": "./src/store/store-template.tsx",
180
- "./store/collection-template": "./src/store/collection-template.tsx",
181
- "./store/category-template": "./src/store/category-template.tsx",
182
- "./store/search-template": "./src/store/search-template.tsx",
183
- "./order": "./src/order/index.ts",
184
- "./order/context": "./src/order/context.tsx",
185
- "./order/labels": "./src/order/labels.ts",
186
- "./order/order-confirmation-header": "./src/order/order-confirmation-header.tsx",
187
- "./order/order-item": "./src/order/order-item.tsx",
188
- "./order/order-items-list": "./src/order/order-items-list.tsx",
189
- "./order/order-totals": "./src/order/order-totals.tsx",
190
- "./order/order-address-card": "./src/order/order-address-card.tsx",
191
- "./order/order-delivery-card": "./src/order/order-delivery-card.tsx",
192
- "./order/order-payment-card": "./src/order/order-payment-card.tsx",
193
- "./order/order-timeline": "./src/order/order-timeline.tsx",
194
- "./order/order-help-section": "./src/order/order-help-section.tsx",
195
- "./order/order-completed-template": "./src/order/order-completed-template.tsx",
196
- "./common": "./src/common/index.ts",
197
- "./common/localized-link": "./src/common/localized-link.tsx",
198
- "./common/cart-button": "./src/common/cart-button.tsx",
199
- "./common/cart-button-client": "./src/common/cart-button-client.tsx",
200
- "./common/delete-button": "./src/common/delete-button.tsx",
201
- "./common/country-flag": "./src/common/country-flag.tsx",
202
- "./common/market-select": "./src/common/market-select.tsx",
203
- "./common/country-select": "./src/common/country-select.tsx",
204
- "./common/language-select": "./src/common/language-select.tsx",
205
- "./common/skeleton": "./src/common/skeleton.tsx",
206
- "./reviews-ui": "./src/reviews-ui/index.ts",
207
- "./locales": "./src/locales/index.ts",
208
- "./locales/en": "./src/locales/en.ts",
209
- "./locales/es": "./src/locales/es.ts",
210
- "./locales/bg": "./src/locales/bg.ts"
211
- },
212
- "dependencies": {
213
- "@radix-ui/react-accordion": "^1.2.12",
214
- "@radix-ui/react-collapsible": "^1.1.12",
215
- "@radix-ui/react-dialog": "^1.1.15",
216
- "@radix-ui/react-dropdown-menu": "^2.1.16",
217
- "@radix-ui/react-label": "^2.1.8",
218
- "@radix-ui/react-popover": "^1.1.15",
219
- "@radix-ui/react-select": "^2.2.6",
220
- "@radix-ui/react-slot": "^1.2.4",
221
- "@radix-ui/react-tabs": "^1.1.13",
222
- "@stripe/react-stripe-js": "^6.1.0",
223
- "@stripe/stripe-js": "^9.1.0",
224
- "class-variance-authority": "^0.7.1",
225
- "clsx": "^2.1.1",
226
- "flag-icons": "^7.5.0",
227
- "lucide-react": "^1.8.0",
228
- "tailwind-merge": "^3.5.0"
229
- },
230
- "scripts": {
231
- "typecheck": "tsc --noEmit"
232
- },
233
- "peerDependencies": {
234
- "next": "^16.0.0",
235
- "react": "^19.0.0",
236
- "react-dom": "^19.0.0"
237
- },
238
- "peerDependenciesMeta": {
239
- "next": {
240
- "optional": true
241
- },
242
- "react": {
243
- "optional": true
244
- },
245
- "react-dom": {
246
- "optional": true
247
- }
248
- },
249
- "devDependencies": {
250
- "@types/node": "^20",
251
- "@types/react": "^19",
252
- "@types/react-dom": "^19",
253
- "typescript": "^5"
254
- },
255
- "engines": {
256
- "node": ">=20"
257
- }
258
- }
1
+ {
2
+ "name": "@cartbase/storefront",
3
+ "version": "0.18.1",
4
+ "description": "Storefront SDK + UI component library for Cartbase stores: typed API client, checkout orchestration, cart drawer, product/catalog components, tracking. Source-shipped TypeScript — add it to transpilePackages.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/Cartbase/cartbase.git",
9
+ "directory": "packages/storefront"
10
+ },
11
+ "type": "module",
12
+ "sideEffects": false,
13
+ "files": [
14
+ "src",
15
+ "theme",
16
+ "README.md"
17
+ ],
18
+ "exports": {
19
+ ".": "./src/index.ts",
20
+ "./api": "./src/api/index.ts",
21
+ "./api/http": "./src/api/http.ts",
22
+ "./api/types": "./src/api/types.ts",
23
+ "./api/products": "./src/api/products.ts",
24
+ "./api/collections": "./src/api/collections.ts",
25
+ "./api/categories": "./src/api/categories.ts",
26
+ "./api/regions": "./src/api/regions.ts",
27
+ "./api/store": "./src/api/store.ts",
28
+ "./api/carts": "./src/api/carts.ts",
29
+ "./api/gift-cards": "./src/api/gift-cards.ts",
30
+ "./api/checkout": "./src/api/checkout.ts",
31
+ "./api/orders": "./src/api/orders.ts",
32
+ "./api/customers": "./src/api/customers.ts",
33
+ "./api/auth": "./src/api/auth.ts",
34
+ "./api/content": "./src/api/content.ts",
35
+ "./api/menus": "./src/api/menus.ts",
36
+ "./api/metaobjects": "./src/api/metaobjects.ts",
37
+ "./api/reviews": "./src/api/reviews.ts",
38
+ "./api/search": "./src/api/search.ts",
39
+ "./api/integrations": "./src/api/integrations.ts",
40
+ "./api/consent": "./src/api/consent.ts",
41
+ "./api/redirects": "./src/api/redirects.ts",
42
+ "./theme": "./theme/index.css",
43
+ "./theme/tokens.css": "./theme/tokens.css",
44
+ "./theme/theme.css": "./theme/theme.css",
45
+ "./lib/utils": "./src/lib/utils.ts",
46
+ "./lib/money": "./src/lib/money.ts",
47
+ "./lib/cart-helpers": "./src/lib/cart-helpers.ts",
48
+ "./lib/get-product-price": "./src/lib/get-product-price.ts",
49
+ "./lib/get-percentage-diff": "./src/lib/get-percentage-diff.ts",
50
+ "./lib/product": "./src/lib/product.ts",
51
+ "./lib/sort-products": "./src/lib/sort-products.ts",
52
+ "./lib/price": "./src/lib/price.tsx",
53
+ "./lib/payment-constants": "./src/lib/payment-constants.ts",
54
+ "./lib/country-name": "./src/lib/country-name.ts",
55
+ "./lib/store-api-error": "./src/lib/store-api-error.ts",
56
+ "./lib/hooks/use-intersection": "./src/lib/hooks/use-intersection.ts",
57
+ "./lib/hooks/use-toggle-state": "./src/lib/hooks/use-toggle-state.ts",
58
+ "./lib/cookie-names": "./src/lib/cookie-names.ts",
59
+ "./lib/media-image": "./src/lib/media-image.tsx",
60
+ "./lib/platform": "./src/lib/platform.ts",
61
+ "./lib/visitor": "./src/lib/visitor.ts",
62
+ "./platform": "./src/platform/index.ts",
63
+ "./platform/identity": "./src/platform/identity.ts",
64
+ "./platform/metadata": "./src/platform/metadata.ts",
65
+ "./platform/platform-init": "./src/platform/platform-init.tsx",
66
+ "./primitives/field": "./src/primitives/field.tsx",
67
+ "./primitives/select-field": "./src/primitives/select-field.tsx",
68
+ "./primitives/ui/accordion": "./src/primitives/ui/accordion.tsx",
69
+ "./primitives/ui/button": "./src/primitives/ui/button.tsx",
70
+ "./primitives/ui/collapsible": "./src/primitives/ui/collapsible.tsx",
71
+ "./primitives/ui/dialog": "./src/primitives/ui/dialog.tsx",
72
+ "./primitives/ui/input": "./src/primitives/ui/input.tsx",
73
+ "./primitives/ui/label": "./src/primitives/ui/label.tsx",
74
+ "./primitives/ui/popover": "./src/primitives/ui/popover.tsx",
75
+ "./primitives/ui/select": "./src/primitives/ui/select.tsx",
76
+ "./primitives/ui/sheet": "./src/primitives/ui/sheet.tsx",
77
+ "./primitives/ui/tabs": "./src/primitives/ui/tabs.tsx",
78
+ "./tracking": "./src/tracking/index.ts",
79
+ "./tracking/types": "./src/tracking/types.ts",
80
+ "./tracking/consent": "./src/tracking/consent.ts",
81
+ "./tracking/consent-init": "./src/tracking/consent-init.tsx",
82
+ "./tracking/consent-banner": "./src/tracking/consent-banner.tsx",
83
+ "./tracking/meta-pixel": "./src/tracking/meta-pixel.tsx",
84
+ "./tracking/ga4": "./src/tracking/ga4.tsx",
85
+ "./tracking/tiktok-pixel": "./src/tracking/tiktok-pixel.tsx",
86
+ "./tracking/ttq": "./src/tracking/ttq.ts",
87
+ "./tracking/events": "./src/tracking/events.ts",
88
+ "./tracking/storefront-tags": "./src/tracking/storefront-tags.tsx",
89
+ "./tracking/track-init": "./src/tracking/track-init.tsx",
90
+ "./tracking/track-order-purchase": "./src/tracking/track-order-purchase.tsx",
91
+ "./tracking/gtm": "./src/tracking/gtm.tsx",
92
+ "./tracking/inline-script": "./src/tracking/inline-script.ts",
93
+ "./tracking/google-ads": "./src/tracking/google-ads.ts",
94
+ "./tracking/rybbit": "./src/tracking/rybbit.tsx",
95
+ "./tracking/rybbit-events": "./src/tracking/rybbit-events.ts",
96
+ "./tracking/fbq": "./src/tracking/fbq.ts",
97
+ "./tracking/gtag": "./src/tracking/gtag.ts",
98
+ "./tracking/attribution": "./src/tracking/attribution.ts",
99
+ "./tracking/get-tracking-config": "./src/tracking/get-tracking-config.ts",
100
+ "./tracking/use-tracking-config": "./src/tracking/use-tracking-config.ts",
101
+ "./tracking/get-tracking-attribution": "./src/tracking/get-tracking-attribution.ts",
102
+ "./tracking/use-engagement-time": "./src/tracking/use-engagement-time.ts",
103
+ "./tracking/page-views": "./src/tracking/page-views.tsx",
104
+ "./tracking/live-heartbeat": "./src/tracking/live-heartbeat.tsx",
105
+ "./checkout": "./src/checkout/index.ts",
106
+ "./checkout/context": "./src/checkout/context.tsx",
107
+ "./checkout/labels": "./src/checkout/labels.ts",
108
+ "./checkout/error-message": "./src/checkout/error-message.tsx",
109
+ "./checkout/stripe-wrapper": "./src/checkout/stripe-wrapper.tsx",
110
+ "./checkout/payment-wrapper": "./src/checkout/payment-wrapper.tsx",
111
+ "./checkout/payment-button": "./src/checkout/payment-button.tsx",
112
+ "./checkout/econt-office-selector": "./src/checkout/econt-office-selector.tsx",
113
+ "./checkout/boxnow-locker-selector": "./src/checkout/boxnow-locker-selector.tsx",
114
+ "./checkout/address-select": "./src/checkout/address-select.tsx",
115
+ "./checkout/company-details": "./src/checkout/company-details.tsx",
116
+ "./checkout/discount-section": "./src/checkout/discount-section.tsx",
117
+ "./checkout/gift-card-section": "./src/checkout/gift-card-section.tsx",
118
+ "./checkout/line-item-card": "./src/checkout/line-item-card.tsx",
119
+ "./checkout/order-summary": "./src/checkout/order-summary.tsx",
120
+ "./checkout/address-form": "./src/checkout/address-form.tsx",
121
+ "./checkout/shipping-method-list": "./src/checkout/shipping-method-list.tsx",
122
+ "./checkout/payment-method-list": "./src/checkout/payment-method-list.tsx",
123
+ "./checkout/checkout-client": "./src/checkout/checkout-client.tsx",
124
+ "./checkout/use-checkout-orchestration": "./src/checkout/use-checkout-orchestration.ts",
125
+ "./checkout/payment-error-copy": "./src/checkout/payment-error-copy.ts",
126
+ "./checkout/address-error-copy": "./src/checkout/address-error-copy.ts",
127
+ "./checkout/promotion-error-copy": "./src/checkout/promotion-error-copy.ts",
128
+ "./cart-drawer": "./src/cart-drawer/index.ts",
129
+ "./cart-drawer/context": "./src/cart-drawer/context.tsx",
130
+ "./cart-drawer/mutation-queue": "./src/cart-drawer/mutation-queue.ts",
131
+ "./cart-drawer/labels": "./src/cart-drawer/labels.ts",
132
+ "./cart-drawer/cart-drawer": "./src/cart-drawer/cart-drawer.tsx",
133
+ "./cart-drawer/header": "./src/cart-drawer/header.tsx",
134
+ "./cart-drawer/promo-banner": "./src/cart-drawer/promo-banner.tsx",
135
+ "./cart-drawer/tiered-progress": "./src/cart-drawer/tiered-progress.tsx",
136
+ "./cart-drawer/item": "./src/cart-drawer/item/index.tsx",
137
+ "./cart-drawer/item/quantity": "./src/cart-drawer/item/quantity.tsx",
138
+ "./cart-drawer/item/variant": "./src/cart-drawer/item/variant.tsx",
139
+ "./cart-drawer/item/upsell": "./src/cart-drawer/item/upsell.tsx",
140
+ "./cart-drawer/free-gift": "./src/cart-drawer/free-gift.tsx",
141
+ "./cart-drawer/gift-wrap": "./src/cart-drawer/gift-wrap.tsx",
142
+ "./cart-drawer/notes": "./src/cart-drawer/notes.tsx",
143
+ "./cart-drawer/rewards-points": "./src/cart-drawer/rewards-points.tsx",
144
+ "./cart-drawer/cross-sell-sidebar": "./src/cart-drawer/cross-sell-sidebar.tsx",
145
+ "./cart-drawer/cross-sell-carousel": "./src/cart-drawer/cross-sell-carousel.tsx",
146
+ "./cart-drawer/summary-breakdown": "./src/cart-drawer/summary-breakdown.tsx",
147
+ "./cart-drawer/sticky-footer": "./src/cart-drawer/sticky-footer.tsx",
148
+ "./cart-drawer/payment-badges": "./src/cart-drawer/payment-badges.tsx",
149
+ "./cart-drawer/continue-shopping": "./src/cart-drawer/continue-shopping.tsx",
150
+ "./cart-drawer/empty": "./src/cart-drawer/empty.tsx",
151
+ "./cart-drawer/template": "./src/cart-drawer/template.tsx",
152
+ "./products": "./src/products/index.ts",
153
+ "./products/context": "./src/products/context.tsx",
154
+ "./products/labels": "./src/products/labels.ts",
155
+ "./products/thumbnail": "./src/products/thumbnail.tsx",
156
+ "./products/preview-price": "./src/products/preview-price.tsx",
157
+ "./products/product-price": "./src/products/product-price.tsx",
158
+ "./products/option-select": "./src/products/option-select.tsx",
159
+ "./products/image-gallery": "./src/products/image-gallery.tsx",
160
+ "./products/variant-url": "./src/products/variant-url.ts",
161
+ "./products/sets": "./src/products/sets.ts",
162
+ "./products/use-product-actions": "./src/products/use-product-actions.ts",
163
+ "./products/product-actions": "./src/products/product-actions.tsx",
164
+ "./products/mobile-actions": "./src/products/mobile-actions.tsx",
165
+ "./products/product-tabs": "./src/products/product-tabs.tsx",
166
+ "./products/product-specs": "./src/products/product-specs.tsx",
167
+ "./products/product-promises": "./src/products/product-promises.tsx",
168
+ "./products/product-info": "./src/products/product-info.tsx",
169
+ "./products/product-preview": "./src/products/product-preview.tsx",
170
+ "./products/related-products": "./src/products/related-products.tsx",
171
+ "./products/product-actions-wrapper": "./src/products/product-actions-wrapper.tsx",
172
+ "./products/product-template": "./src/products/product-template.tsx",
173
+ "./store": "./src/store/index.ts",
174
+ "./store/labels": "./src/store/labels.ts",
175
+ "./store/pagination": "./src/store/pagination.tsx",
176
+ "./store/sort-select": "./src/store/sort-select.tsx",
177
+ "./store/paginated-products": "./src/store/paginated-products.tsx",
178
+ "./store/skeleton-product-grid": "./src/store/skeleton-product-grid.tsx",
179
+ "./store/store-template": "./src/store/store-template.tsx",
180
+ "./store/collection-template": "./src/store/collection-template.tsx",
181
+ "./store/category-template": "./src/store/category-template.tsx",
182
+ "./store/search-template": "./src/store/search-template.tsx",
183
+ "./order": "./src/order/index.ts",
184
+ "./order/context": "./src/order/context.tsx",
185
+ "./order/labels": "./src/order/labels.ts",
186
+ "./order/order-confirmation-header": "./src/order/order-confirmation-header.tsx",
187
+ "./order/order-item": "./src/order/order-item.tsx",
188
+ "./order/order-items-list": "./src/order/order-items-list.tsx",
189
+ "./order/order-totals": "./src/order/order-totals.tsx",
190
+ "./order/order-address-card": "./src/order/order-address-card.tsx",
191
+ "./order/order-delivery-card": "./src/order/order-delivery-card.tsx",
192
+ "./order/order-payment-card": "./src/order/order-payment-card.tsx",
193
+ "./order/order-timeline": "./src/order/order-timeline.tsx",
194
+ "./order/order-help-section": "./src/order/order-help-section.tsx",
195
+ "./order/order-completed-template": "./src/order/order-completed-template.tsx",
196
+ "./common": "./src/common/index.ts",
197
+ "./common/localized-link": "./src/common/localized-link.tsx",
198
+ "./common/cart-button": "./src/common/cart-button.tsx",
199
+ "./common/cart-button-client": "./src/common/cart-button-client.tsx",
200
+ "./common/delete-button": "./src/common/delete-button.tsx",
201
+ "./common/country-flag": "./src/common/country-flag.tsx",
202
+ "./common/market-select": "./src/common/market-select.tsx",
203
+ "./common/country-select": "./src/common/country-select.tsx",
204
+ "./common/language-select": "./src/common/language-select.tsx",
205
+ "./common/skeleton": "./src/common/skeleton.tsx",
206
+ "./reviews-ui": "./src/reviews-ui/index.ts",
207
+ "./locales": "./src/locales/index.ts",
208
+ "./locales/en": "./src/locales/en.ts",
209
+ "./locales/es": "./src/locales/es.ts",
210
+ "./locales/bg": "./src/locales/bg.ts"
211
+ },
212
+ "dependencies": {
213
+ "@radix-ui/react-accordion": "^1.2.12",
214
+ "@radix-ui/react-collapsible": "^1.1.12",
215
+ "@radix-ui/react-dialog": "^1.1.15",
216
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
217
+ "@radix-ui/react-label": "^2.1.8",
218
+ "@radix-ui/react-popover": "^1.1.15",
219
+ "@radix-ui/react-select": "^2.2.6",
220
+ "@radix-ui/react-slot": "^1.2.4",
221
+ "@radix-ui/react-tabs": "^1.1.13",
222
+ "@stripe/react-stripe-js": "^6.1.0",
223
+ "@stripe/stripe-js": "^9.1.0",
224
+ "class-variance-authority": "^0.7.1",
225
+ "clsx": "^2.1.1",
226
+ "flag-icons": "^7.5.0",
227
+ "lucide-react": "^1.8.0",
228
+ "tailwind-merge": "^3.5.0"
229
+ },
230
+ "scripts": {
231
+ "typecheck": "tsc --noEmit"
232
+ },
233
+ "peerDependencies": {
234
+ "next": "^16.0.0",
235
+ "react": "^19.0.0",
236
+ "react-dom": "^19.0.0"
237
+ },
238
+ "peerDependenciesMeta": {
239
+ "next": {
240
+ "optional": true
241
+ },
242
+ "react": {
243
+ "optional": true
244
+ },
245
+ "react-dom": {
246
+ "optional": true
247
+ }
248
+ },
249
+ "devDependencies": {
250
+ "@types/node": "^20",
251
+ "@types/react": "^19",
252
+ "@types/react-dom": "^19",
253
+ "typescript": "^5"
254
+ },
255
+ "engines": {
256
+ "node": ">=20"
257
+ }
258
+ }
@@ -134,6 +134,20 @@ export type CartMutationResult =
134
134
  /** The id prefix of a line the platform has not confirmed yet. */
135
135
  const PENDING_PREFIX = "optimistic-"
136
136
 
137
+ /**
138
+ * A cart that can still be shopped. A completed cart is an order now: the
139
+ * platform still answers it, lines and all, but refuses every change to it.
140
+ */
141
+ export function isLiveCart(cart: Cart | null | undefined): cart is Cart {
142
+ return Boolean(cart && !cart.completed_at)
143
+ }
144
+
145
+ /** The platform's answer that the cart a change was aimed at is over (ordered, or gone). */
146
+ export function isEndedCartError(err: unknown): boolean {
147
+ const code = (err as { code?: unknown } | null)?.code
148
+ return code === "cart_completed" || code === "cart_not_found"
149
+ }
150
+
137
151
  /**
138
152
  * A line the platform has not confirmed yet: it was added a moment ago and
139
153
  * carries a placeholder id. Its quantity and removal work already (the
@@ -196,6 +210,12 @@ type CartDrawerContextValue = {
196
210
  removeItem: (lineId: string) => Promise<boolean>
197
211
  /** Re-read the decorated cart (totals/gift-card tender are live per read). */
198
212
  refresh: () => Promise<void>
213
+ /**
214
+ * The cart is over (the order was placed): the drawer empties and the
215
+ * store's `onCartEnd` clears its cookie. The checkout calls it; the next
216
+ * add starts a new cart.
217
+ */
218
+ forget: () => Promise<void>
199
219
  /** True when the provider was given a client, so the methods above reach the platform. */
200
220
  canMutate: boolean
201
221
  labels: CartDrawerLabels
@@ -215,6 +235,7 @@ const CartDrawerContext = createContext<CartDrawerContextValue>({
215
235
  updateQuantity: async () => false,
216
236
  removeItem: async () => false,
217
237
  refresh: async () => {},
238
+ forget: async () => {},
218
239
  canMutate: false,
219
240
  labels: defaultCartDrawerLabels,
220
241
  hrefs: defaultHrefs,
@@ -351,6 +372,7 @@ export function CartDrawerProvider({
351
372
  client,
352
373
  cartId,
353
374
  onCartChange,
375
+ onCartEnd,
354
376
  onOptimisticError,
355
377
  labels: labelOverrides,
356
378
  hrefs: hrefOverrides,
@@ -374,6 +396,13 @@ export function CartDrawerProvider({
374
396
  * here so the cart survives reloads.
375
397
  */
376
398
  onCartChange?: (cart: Cart) => void
399
+ /**
400
+ * Fires when the cart is over: the order was placed, or the platform
401
+ * answered that the stored cart is completed or gone. Clear the stored
402
+ * cart id (the cookie) here; the next add creates a new cart and
403
+ * `onCartChange` stores its id.
404
+ */
405
+ onCartEnd?: () => void
377
406
  /** Ops funnel for every failed optimistic mutation (see module JSDoc). */
378
407
  onOptimisticError?: (failure: OptimisticCartError) => void
379
408
  /**
@@ -392,27 +421,55 @@ export function CartDrawerProvider({
392
421
  // it reads when a change's turn comes (state lags a render behind).
393
422
  const queue = useRef<CartMutationQueue | null>(null)
394
423
  if (!queue.current) queue.current = createCartMutationQueue()
395
- const latest = useRef<Cart | null>(cart ?? null)
424
+ // A completed cart is an order: the drawer never holds one.
425
+ const latest = useRef<Cart | null>(isLiveCart(cart) ? cart : null)
426
+
427
+ // The store's hooks, read through refs so an inline handler never re-runs an effect.
428
+ const cartEnded = useRef(onCartEnd)
429
+ cartEnded.current = onCartEnd
396
430
 
397
431
  // Confirmed snapshot: seeded from the prop, replaced by every SDK
398
432
  // mutation response and by prop updates from server refreshes.
399
- const [serverCart, setServerCart] = useState<Cart | null>(cart ?? null)
433
+ const [serverCart, setServerCart] = useState<Cart | null>(latest.current)
434
+
435
+ /** The cart is over: the drawer empties and the store forgets the id. */
436
+ const end = useCallback(() => {
437
+ latest.current = null
438
+ startTransition(() => setServerCart(null))
439
+ try {
440
+ cartEnded.current?.()
441
+ } catch {
442
+ // A store's handler must never break the drawer.
443
+ }
444
+ }, [])
445
+
400
446
  useEffect(() => {
401
447
  if (cart === undefined) return
402
448
  // A refresh carrying the cart as it was must not overwrite an answer
403
449
  // still on its way; the queue's own answers are newer.
404
450
  if (queue.current?.busy()) return
451
+ if (cart && !isLiveCart(cart)) {
452
+ end()
453
+ return
454
+ }
405
455
  latest.current = cart
406
456
  setServerCart(cart)
407
- }, [cart])
457
+ }, [cart, end])
408
458
 
409
459
  // A confirmed cart becomes the snapshot inside a transition, so it lands
410
460
  // together with the end of the change that asked for it and a pending
411
- // line is never shown twice.
412
- const adopt = useCallback((next: Cart) => {
413
- latest.current = next
414
- startTransition(() => setServerCart(next))
415
- }, [])
461
+ // line is never shown twice. A completed one ends the cart instead.
462
+ const adopt = useCallback(
463
+ (next: Cart) => {
464
+ if (!isLiveCart(next)) {
465
+ end()
466
+ return
467
+ }
468
+ latest.current = next
469
+ startTransition(() => setServerCart(next))
470
+ },
471
+ [end]
472
+ )
416
473
 
417
474
  // Client+cartId mode: read the cart on mount, through the queue, so an
418
475
  // add made before the read answers goes to this cart, not a new one.
@@ -423,15 +480,16 @@ export function CartDrawerProvider({
423
480
  try {
424
481
  const res = await sdkRetrieveCart(client, cartId)
425
482
  if (!cancelled) adopt(res.cart)
426
- } catch {
427
- // 404 cart_not_found (expired/foreign id) stay empty; the next
428
- // addLine creates a fresh cart.
483
+ } catch (err) {
484
+ // A stored id the platform no longer knows: forget it. Any other
485
+ // failure (a network blip) keeps the id for the next visit.
486
+ if (!cancelled && isEndedCartError(err)) end()
429
487
  }
430
488
  })
431
489
  return () => {
432
490
  cancelled = true
433
491
  }
434
- }, [cart, client, cartId, adopt])
492
+ }, [cart, client, cartId, adopt, end])
435
493
 
436
494
  const [optimisticCart, dispatchOptimistic] = useOptimistic(
437
495
  serverCart,
@@ -532,7 +590,8 @@ export function CartDrawerProvider({
532
590
  const confirm = useCallback(
533
591
  (next: Cart) => {
534
592
  adopt(next)
535
- onCartChange?.(next)
593
+ // A completed cart has ended the cart; its id is never stored again.
594
+ if (isLiveCart(next)) onCartChange?.(next)
536
595
  },
537
596
  [adopt, onCartChange]
538
597
  )
@@ -561,13 +620,26 @@ export function CartDrawerProvider({
561
620
  ...display,
562
621
  }
563
622
  const work = queue.current!.run(async (): Promise<CartMutationResult> => {
623
+ // First add with no cart: create one with the item in a single
624
+ // call. region_id falls back to the store default server-side.
625
+ const create = () => sdkCreateCart(client, { items: [{ variant_id: variantId, quantity }] })
564
626
  try {
565
627
  const cartId = latest.current?.id
566
- const res = cartId
567
- ? await sdkAddLineItem(client, cartId, { variant_id: variantId, quantity })
568
- : // First add with no cart: create one with the item in a single
569
- // call. region_id falls back to the store default server-side.
570
- await sdkCreateCart(client, { items: [{ variant_id: variantId, quantity }] })
628
+ let res
629
+ if (!cartId) {
630
+ res = await create()
631
+ } else {
632
+ try {
633
+ res = await sdkAddLineItem(client, cartId, { variant_id: variantId, quantity })
634
+ } catch (error) {
635
+ // The stored cart is over (ordered in another tab, or gone):
636
+ // Medusa's starter treats it as no cart, so a new one starts
637
+ // with this item.
638
+ if (!isEndedCartError(error)) throw error
639
+ end()
640
+ res = await create()
641
+ }
642
+ }
571
643
  confirm(res.cart)
572
644
  return { ok: true, cart: res.cart }
573
645
  } catch (error) {
@@ -577,7 +649,7 @@ export function CartDrawerProvider({
577
649
  })
578
650
  return showWhile(action, work)
579
651
  },
580
- [client, confirm, report, showWhile]
652
+ [client, confirm, report, showWhile, end]
581
653
  )
582
654
 
583
655
  const addItem = useCallback(
@@ -599,7 +671,8 @@ export function CartDrawerProvider({
599
671
  confirm(res.cart)
600
672
  return true
601
673
  } catch (err) {
602
- report({ type: "update_quantity", lineId, quantity: latestQuantity }, err)
674
+ if (isEndedCartError(err)) end()
675
+ else report({ type: "update_quantity", lineId, quantity: latestQuantity }, err)
603
676
  return false
604
677
  }
605
678
  })
@@ -608,7 +681,7 @@ export function CartDrawerProvider({
608
681
  work.then((sent) => sent === true)
609
682
  )
610
683
  },
611
- [client, lineNow, confirm, report, showWhile]
684
+ [client, lineNow, confirm, report, showWhile, end]
612
685
  )
613
686
 
614
687
  const removeItem = useCallback(
@@ -627,13 +700,17 @@ export function CartDrawerProvider({
627
700
  confirm(res.cart)
628
701
  return true
629
702
  } catch (err) {
703
+ if (isEndedCartError(err)) {
704
+ end()
705
+ return true
706
+ }
630
707
  report(action, err)
631
708
  return false
632
709
  }
633
710
  })
634
711
  return showWhile(action, work)
635
712
  },
636
- [client, lineNow, confirm, report, showWhile]
713
+ [client, lineNow, confirm, report, showWhile, end]
637
714
  )
638
715
 
639
716
  const refresh = useCallback(
@@ -645,12 +722,20 @@ export function CartDrawerProvider({
645
722
  try {
646
723
  const res = await sdkRetrieveCart(client, id)
647
724
  confirm(res.cart)
648
- } catch {
649
- // Keep the last snapshot on transient failure.
725
+ } catch (err) {
726
+ // A cart the platform no longer knows ends; a transient failure
727
+ // keeps the last snapshot.
728
+ if (isEndedCartError(err)) end()
650
729
  }
651
730
  })
652
731
  },
653
- [client, confirm]
732
+ [client, confirm, end]
733
+ )
734
+
735
+ /** The order was placed: empty the drawer and let the store forget the id. */
736
+ const forget = useCallback(
737
+ (): Promise<void> => queue.current!.run(async () => end()),
738
+ [end]
654
739
  )
655
740
 
656
741
  // The mounted language is the default (2026-09-14): a store that mounts
@@ -681,6 +766,7 @@ export function CartDrawerProvider({
681
766
  updateQuantity,
682
767
  removeItem,
683
768
  refresh,
769
+ forget,
684
770
  canMutate: Boolean(client),
685
771
  labels,
686
772
  hrefs,
@@ -21,6 +21,8 @@ export {
21
21
  reduceCart,
22
22
  makeOptimisticLine,
23
23
  isPendingLine,
24
+ isLiveCart,
25
+ isEndedCartError,
24
26
  type CartMutationResult,
25
27
  type OptimisticCartAction,
26
28
  type OptimisticAddDisplay,
@@ -41,6 +41,8 @@ import {
41
41
  type UpdateCustomerInput,
42
42
  } from "../api/customers"
43
43
  import { isStripeLike } from "../lib/payment-constants"
44
+ import { clearCartCookie } from "../lib/cookie-names"
45
+ import { useCartDrawer } from "../cart-drawer/context"
44
46
  import compareAddresses from "./compare-addresses"
45
47
  import { translateAddressError } from "./address-error-copy"
46
48
  import { translatePaymentError } from "./payment-error-copy"
@@ -303,6 +305,9 @@ export function useCheckoutOrchestration({
303
305
  const contextOrderConfirmedPath = useOrderConfirmedPath()
304
306
  const orderConfirmedPath =
305
307
  orderConfirmedPathProp ?? contextOrderConfirmedPath
308
+ // The mounted cart drawer, emptied when the order is placed (a no-op
309
+ // when the store mounts none).
310
+ const { forget: forgetCart } = useCartDrawer()
306
311
 
307
312
  // ── Completed-cart detection ────────────────────────────────────────
308
313
  // Surfaced as a flag so the page-level server component can redirect
@@ -1041,6 +1046,12 @@ export function useCheckoutOrchestration({
1041
1046
 
1042
1047
  const { order } = await completeCart(client, cart.id)
1043
1048
 
1049
+ // The cart is an order now (Medusa's placeOrder: removeCartId()): the
1050
+ // stored id goes and the drawer empties, so the next add starts a new
1051
+ // cart instead of being refused by the completed one.
1052
+ clearCartCookie()
1053
+ await forgetCart()
1054
+
1044
1055
  if (onOrderPlaced) {
1045
1056
  onOrderPlaced(order)
1046
1057
  } else if (typeof window !== "undefined") {
@@ -1057,6 +1068,7 @@ export function useCheckoutOrchestration({
1057
1068
  client,
1058
1069
  cart.id,
1059
1070
  cart.metadata,
1071
+ forgetCart,
1060
1072
  onOrderPlaced,
1061
1073
  orderConfirmedPath,
1062
1074
  resolveTrackingMetadata,
@@ -40,6 +40,20 @@ export function readCartCookie(
40
40
  return get(CART_COOKIE) ?? get(LEGACY_CART_COOKIE)
41
41
  }
42
42
 
43
+ /**
44
+ * Forget the stored cart in the browser, under both names: Medusa's
45
+ * `removeCartId()`. The package's checkout calls it when the order is
46
+ * placed, and a store hands it to `CartDrawerProvider`'s `onCartEnd` so a
47
+ * cart that turned out to be completed or gone is forgotten too. A no-op
48
+ * on the server.
49
+ */
50
+ export function clearCartCookie(): void {
51
+ if (typeof document === "undefined") return
52
+ for (const name of [CART_COOKIE, LEGACY_CART_COOKIE]) {
53
+ document.cookie = `${name}=;path=/;max-age=0;samesite=lax`
54
+ }
55
+ }
56
+
43
57
  /**
44
58
  * THE VISITOR ID — our own per-browser id and the join key between browsing
45
59
  * and money (ecommerce-analytics §3.1). It is OURS deliberately: the