@shopkit/cart 0.1.0
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/CHANGELOG.md +58 -0
- package/README.md +216 -0
- package/dist/index.d.mts +730 -0
- package/dist/index.d.ts +730 -0
- package/dist/index.js +2 -0
- package/dist/index.mjs +2 -0
- package/package.json +60 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,730 @@
|
|
|
1
|
+
import * as zustand from 'zustand';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @shopkit/cart - Cart Module Types
|
|
5
|
+
*
|
|
6
|
+
* Single source of truth for all cart-related types and interfaces.
|
|
7
|
+
* This module is designed to be merchant-agnostic and package-ready.
|
|
8
|
+
*
|
|
9
|
+
* @packageDocumentation
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Represents an item in the shopping cart.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const item: CartItem = {
|
|
17
|
+
* id: "gid://shopify/CartLine/123",
|
|
18
|
+
* productId: "gid://shopify/Product/456",
|
|
19
|
+
* variantId: "gid://shopify/ProductVariant/789",
|
|
20
|
+
* title: "Premium T-Shirt",
|
|
21
|
+
* quantity: 2,
|
|
22
|
+
* price: { amount: 29.99, currencyCode: "USD" },
|
|
23
|
+
* image: "https://example.com/image.jpg"
|
|
24
|
+
* };
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
interface CartItem {
|
|
28
|
+
/** Unique identifier for the cart line item */
|
|
29
|
+
id: string;
|
|
30
|
+
/** Product identifier */
|
|
31
|
+
productId: string;
|
|
32
|
+
/** Optional variant identifier */
|
|
33
|
+
variantId?: string;
|
|
34
|
+
/** Product title */
|
|
35
|
+
title: string;
|
|
36
|
+
/** Current price of the item */
|
|
37
|
+
price: {
|
|
38
|
+
amount: number;
|
|
39
|
+
currencyCode: string;
|
|
40
|
+
};
|
|
41
|
+
/** Original price before discounts (for showing savings) */
|
|
42
|
+
compareAtPrice?: {
|
|
43
|
+
amount: number;
|
|
44
|
+
currencyCode: string;
|
|
45
|
+
};
|
|
46
|
+
/** Quantity of this item in cart */
|
|
47
|
+
quantity: number;
|
|
48
|
+
/** Product image URL */
|
|
49
|
+
image?: string;
|
|
50
|
+
/** Product vendor/brand */
|
|
51
|
+
vendor?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Request payload for adding/updating cart items.
|
|
55
|
+
* Used when communicating with the cart service.
|
|
56
|
+
*/
|
|
57
|
+
interface CartItemRequest {
|
|
58
|
+
/** Product identifier */
|
|
59
|
+
productId: string;
|
|
60
|
+
/** Variant identifier */
|
|
61
|
+
variantId: string;
|
|
62
|
+
/** Quantity to add/set */
|
|
63
|
+
quantity: number;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Response from cart API operations.
|
|
67
|
+
* Contains the full cart state after an operation.
|
|
68
|
+
*/
|
|
69
|
+
interface CartResponse {
|
|
70
|
+
/** Cart identifier */
|
|
71
|
+
id: string;
|
|
72
|
+
/** Items currently in the cart */
|
|
73
|
+
items: CartItem[];
|
|
74
|
+
/** Subtotal before discounts */
|
|
75
|
+
subtotal?: {
|
|
76
|
+
amount: number;
|
|
77
|
+
currencyCode: string;
|
|
78
|
+
};
|
|
79
|
+
/** Total amount after discounts */
|
|
80
|
+
totalAmount?: {
|
|
81
|
+
amount: number;
|
|
82
|
+
currencyCode: string;
|
|
83
|
+
};
|
|
84
|
+
/** URL to proceed to checkout */
|
|
85
|
+
checkoutUrl?: string;
|
|
86
|
+
/** Timestamp when cart was created */
|
|
87
|
+
createdAt?: string;
|
|
88
|
+
/** Timestamp when cart was last updated */
|
|
89
|
+
updatedAt?: string;
|
|
90
|
+
[key: string]: any;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Interface for cart service implementations.
|
|
94
|
+
* Implement this interface to create custom cart backends.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* class MyCartService implements ICartService {
|
|
99
|
+
* async createCart(merchantName: string): Promise<CartResponse> {
|
|
100
|
+
* // Your implementation
|
|
101
|
+
* }
|
|
102
|
+
* async getCart(cartId: string): Promise<CartResponse> {
|
|
103
|
+
* // Your implementation
|
|
104
|
+
* }
|
|
105
|
+
* // ... other methods
|
|
106
|
+
* }
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
interface ICartService {
|
|
110
|
+
/**
|
|
111
|
+
* Create a new cart for the given merchant.
|
|
112
|
+
* @param merchantName - Unique identifier for the merchant
|
|
113
|
+
* @returns The newly created cart
|
|
114
|
+
*/
|
|
115
|
+
createCart(merchantName: string): Promise<CartResponse>;
|
|
116
|
+
/**
|
|
117
|
+
* Retrieve an existing cart by ID.
|
|
118
|
+
* @param cartId - The cart identifier
|
|
119
|
+
* @returns The cart data
|
|
120
|
+
*/
|
|
121
|
+
getCart(cartId: string): Promise<CartResponse>;
|
|
122
|
+
/**
|
|
123
|
+
* Add items to the cart.
|
|
124
|
+
* @param cartId - The cart identifier
|
|
125
|
+
* @param items - Array of items to add
|
|
126
|
+
*/
|
|
127
|
+
addToCart(cartId: string, items: CartItemRequest[]): Promise<void>;
|
|
128
|
+
/**
|
|
129
|
+
* Remove items from the cart.
|
|
130
|
+
* @param cartId - The cart identifier
|
|
131
|
+
* @param itemIds - Array of cart line item IDs to remove
|
|
132
|
+
*/
|
|
133
|
+
removeFromCart(cartId: string, itemIds: string[]): Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* Update item quantities in the cart.
|
|
136
|
+
* @param cartId - The cart identifier
|
|
137
|
+
* @param items - Array of items with updated quantities
|
|
138
|
+
*/
|
|
139
|
+
updateCart(cartId: string, items: CartItemRequest[]): Promise<void>;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Interface for cart storage implementations.
|
|
143
|
+
* Implement this interface to customize how cart IDs are persisted.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```typescript
|
|
147
|
+
* class CookieCartStorage implements ICartStorage {
|
|
148
|
+
* getCartId(): string | null {
|
|
149
|
+
* return getCookie('cart-id');
|
|
150
|
+
* }
|
|
151
|
+
* setCartId(cartId: string): void {
|
|
152
|
+
* setCookie('cart-id', cartId);
|
|
153
|
+
* }
|
|
154
|
+
* // ... other methods
|
|
155
|
+
* }
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
interface ICartStorage {
|
|
159
|
+
/**
|
|
160
|
+
* Get the stored cart ID.
|
|
161
|
+
* @returns The cart ID or null if not found
|
|
162
|
+
*/
|
|
163
|
+
getCartId(): string | null;
|
|
164
|
+
/**
|
|
165
|
+
* Store the cart ID.
|
|
166
|
+
* @param cartId - The cart ID to store
|
|
167
|
+
*/
|
|
168
|
+
setCartId(cartId: string): void;
|
|
169
|
+
/**
|
|
170
|
+
* Remove the stored cart ID.
|
|
171
|
+
*/
|
|
172
|
+
removeCartId(): void;
|
|
173
|
+
/**
|
|
174
|
+
* Clear all cart-related storage.
|
|
175
|
+
*/
|
|
176
|
+
clear(): void;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Configuration options for the cart module.
|
|
180
|
+
* Pass to `configureCart()` at app initialization.
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```typescript
|
|
184
|
+
* const config: CartConfig = {
|
|
185
|
+
* merchantName: "my-store",
|
|
186
|
+
* cartService: new DefaultCartService("/api/cart"),
|
|
187
|
+
* cartStorage: new DefaultCartStorage("my-store"),
|
|
188
|
+
* defaultCurrencyCode: "USD",
|
|
189
|
+
* onCartEvent: (event) => console.log("Cart event:", event),
|
|
190
|
+
* };
|
|
191
|
+
* configureCart(config);
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
interface CartConfig {
|
|
195
|
+
/** Unique identifier for the merchant/store */
|
|
196
|
+
merchantName: string;
|
|
197
|
+
/** Service instance for cart API operations */
|
|
198
|
+
cartService: ICartService;
|
|
199
|
+
/** Storage instance for cart persistence */
|
|
200
|
+
cartStorage: ICartStorage;
|
|
201
|
+
/** Default currency code for price formatting (default: "USD") */
|
|
202
|
+
defaultCurrencyCode?: string;
|
|
203
|
+
/** Optional callback for cart events (analytics, logging, etc.) */
|
|
204
|
+
onCartEvent?: (event: CartEvent) => void;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Events emitted by the cart store.
|
|
208
|
+
* Subscribe via the `onCartEvent` callback in CartConfig.
|
|
209
|
+
*/
|
|
210
|
+
type CartEvent = {
|
|
211
|
+
type: "CART_INITIALIZED";
|
|
212
|
+
cartId: string;
|
|
213
|
+
} | {
|
|
214
|
+
type: "ADD_TO_CART";
|
|
215
|
+
item: CartItem;
|
|
216
|
+
} | {
|
|
217
|
+
type: "REMOVE_FROM_CART";
|
|
218
|
+
item: CartItem;
|
|
219
|
+
} | {
|
|
220
|
+
type: "UPDATE_QUANTITY";
|
|
221
|
+
item: CartItem;
|
|
222
|
+
previousQuantity: number;
|
|
223
|
+
} | {
|
|
224
|
+
type: "CLEAR_CART";
|
|
225
|
+
itemCount: number;
|
|
226
|
+
} | {
|
|
227
|
+
type: "CART_OPENED";
|
|
228
|
+
} | {
|
|
229
|
+
type: "CART_CLOSED";
|
|
230
|
+
} | {
|
|
231
|
+
type: "CART_ERROR";
|
|
232
|
+
action: string;
|
|
233
|
+
error: string;
|
|
234
|
+
};
|
|
235
|
+
/**
|
|
236
|
+
* The state shape of the cart store.
|
|
237
|
+
* Access via `useCartStore()` hook.
|
|
238
|
+
*/
|
|
239
|
+
interface CartState {
|
|
240
|
+
/** Items currently in the cart */
|
|
241
|
+
items: CartItem[];
|
|
242
|
+
/** Whether the cart drawer/modal is open */
|
|
243
|
+
isOpen: boolean;
|
|
244
|
+
/** Whether a cart operation is in progress */
|
|
245
|
+
isLoading: boolean;
|
|
246
|
+
/** Current error message, if any */
|
|
247
|
+
error: string | null;
|
|
248
|
+
/** Current cart identifier */
|
|
249
|
+
cartId: string | null;
|
|
250
|
+
/** URL to proceed to checkout */
|
|
251
|
+
checkoutUrl?: string;
|
|
252
|
+
/** Server-calculated total amount */
|
|
253
|
+
totalAmount?: {
|
|
254
|
+
amount: number;
|
|
255
|
+
currencyCode: string;
|
|
256
|
+
};
|
|
257
|
+
/** Whether the cart has been initialized */
|
|
258
|
+
isInitialized: boolean;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Actions available on the cart store.
|
|
262
|
+
*/
|
|
263
|
+
interface CartActions {
|
|
264
|
+
/**
|
|
265
|
+
* Initialize the cart. Restores from storage or creates new.
|
|
266
|
+
* @param merchantName - Optional merchant name override
|
|
267
|
+
*/
|
|
268
|
+
initializeCart: (merchantName?: string) => Promise<void>;
|
|
269
|
+
/**
|
|
270
|
+
* Add a single item to the cart.
|
|
271
|
+
* @param item - The cart item to add
|
|
272
|
+
*/
|
|
273
|
+
addItem: (item: CartItem) => Promise<void>;
|
|
274
|
+
/**
|
|
275
|
+
* Add multiple items to the cart.
|
|
276
|
+
* @param items - Array of items to add
|
|
277
|
+
*/
|
|
278
|
+
addItems: (items: CartItemRequest[]) => Promise<void>;
|
|
279
|
+
/**
|
|
280
|
+
* Remove an item from the cart.
|
|
281
|
+
* @param lineId - Cart line item ID
|
|
282
|
+
* @param variantId - Optional variant ID for identification
|
|
283
|
+
*/
|
|
284
|
+
removeItem: (lineId: string, variantId?: string) => Promise<void>;
|
|
285
|
+
/**
|
|
286
|
+
* Update the quantity of an item.
|
|
287
|
+
* @param lineId - Cart line item ID
|
|
288
|
+
* @param quantity - New quantity
|
|
289
|
+
* @param variantId - Optional variant ID for identification
|
|
290
|
+
*/
|
|
291
|
+
updateItemQuantity: (lineId: string, quantity: number, variantId?: string) => Promise<void>;
|
|
292
|
+
/**
|
|
293
|
+
* Clear all items from the cart.
|
|
294
|
+
*/
|
|
295
|
+
clearCart: () => Promise<void>;
|
|
296
|
+
/**
|
|
297
|
+
* Open the cart drawer/modal.
|
|
298
|
+
*/
|
|
299
|
+
openCart: () => Promise<void>;
|
|
300
|
+
/**
|
|
301
|
+
* Close the cart drawer/modal.
|
|
302
|
+
*/
|
|
303
|
+
closeCart: () => void;
|
|
304
|
+
/**
|
|
305
|
+
* Toggle the cart drawer/modal open/closed.
|
|
306
|
+
*/
|
|
307
|
+
toggleCart: () => Promise<void>;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Configure the cart module with required services.
|
|
312
|
+
* Must be called before using the cart store.
|
|
313
|
+
*/
|
|
314
|
+
declare function configureCart(config: CartConfig): void;
|
|
315
|
+
/**
|
|
316
|
+
* Get the current cart configuration.
|
|
317
|
+
* Throws if cart is not configured.
|
|
318
|
+
*/
|
|
319
|
+
declare function getCartConfig(): CartConfig;
|
|
320
|
+
/**
|
|
321
|
+
* Check if cart is configured.
|
|
322
|
+
*/
|
|
323
|
+
declare function isCartConfigured(): boolean;
|
|
324
|
+
declare const useCartStore: zustand.UseBoundStore<zustand.StoreApi<CartState & CartActions>>;
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Hook to get the number of unique items in the cart.
|
|
328
|
+
*
|
|
329
|
+
* @returns The count of unique items (not total quantity)
|
|
330
|
+
*
|
|
331
|
+
* @example
|
|
332
|
+
* ```tsx
|
|
333
|
+
* function CartBadge() {
|
|
334
|
+
* const count = useCartCount();
|
|
335
|
+
* return <span>{count} items</span>;
|
|
336
|
+
* }
|
|
337
|
+
* ```
|
|
338
|
+
*/
|
|
339
|
+
declare const useCartCount: () => number;
|
|
340
|
+
/**
|
|
341
|
+
* Hook to get the total quantity of all items in the cart.
|
|
342
|
+
* This sums up quantities across all items.
|
|
343
|
+
*
|
|
344
|
+
* @returns The sum of all item quantities
|
|
345
|
+
*
|
|
346
|
+
* @example
|
|
347
|
+
* ```tsx
|
|
348
|
+
* function CartIcon() {
|
|
349
|
+
* const totalQty = useCartTotalQuantity();
|
|
350
|
+
* return <Badge count={totalQty}><ShoppingCart /></Badge>;
|
|
351
|
+
* }
|
|
352
|
+
* ```
|
|
353
|
+
*/
|
|
354
|
+
declare const useCartTotalQuantity: () => number;
|
|
355
|
+
/**
|
|
356
|
+
* Hook to get all cart items.
|
|
357
|
+
*
|
|
358
|
+
* @returns Array of cart items
|
|
359
|
+
*
|
|
360
|
+
* @example
|
|
361
|
+
* ```tsx
|
|
362
|
+
* function CartItemsList() {
|
|
363
|
+
* const items = useCartItems();
|
|
364
|
+
* return (
|
|
365
|
+
* <ul>
|
|
366
|
+
* {items.map(item => (
|
|
367
|
+
* <li key={item.id}>{item.title} x {item.quantity}</li>
|
|
368
|
+
* ))}
|
|
369
|
+
* </ul>
|
|
370
|
+
* );
|
|
371
|
+
* }
|
|
372
|
+
* ```
|
|
373
|
+
*/
|
|
374
|
+
declare const useCartItems: () => CartItem[];
|
|
375
|
+
/**
|
|
376
|
+
* Hook to get the cart toggle function.
|
|
377
|
+
* Call the returned function to toggle cart open/closed.
|
|
378
|
+
*
|
|
379
|
+
* @returns Function to toggle cart visibility
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* ```tsx
|
|
383
|
+
* function CartButton() {
|
|
384
|
+
* const toggleCart = useCartToggle();
|
|
385
|
+
* return <button onClick={toggleCart}>Toggle Cart</button>;
|
|
386
|
+
* }
|
|
387
|
+
* ```
|
|
388
|
+
*/
|
|
389
|
+
declare const useCartToggle: () => () => Promise<void>;
|
|
390
|
+
/**
|
|
391
|
+
* Hook to get cart status information.
|
|
392
|
+
*
|
|
393
|
+
* @returns Object with isOpen, isLoading, error, cartId, and isInitialized
|
|
394
|
+
*
|
|
395
|
+
* @example
|
|
396
|
+
* ```tsx
|
|
397
|
+
* function CartStatus() {
|
|
398
|
+
* const { isOpen, isLoading, error } = useCartStatus();
|
|
399
|
+
* if (isLoading) return <Spinner />;
|
|
400
|
+
* if (error) return <Error message={error} />;
|
|
401
|
+
* return <div>Cart is {isOpen ? 'open' : 'closed'}</div>;
|
|
402
|
+
* }
|
|
403
|
+
* ```
|
|
404
|
+
*/
|
|
405
|
+
declare const useCartStatus: () => {
|
|
406
|
+
isOpen: boolean;
|
|
407
|
+
isLoading: boolean;
|
|
408
|
+
error: string | null;
|
|
409
|
+
cartId: string | null;
|
|
410
|
+
isInitialized: boolean;
|
|
411
|
+
};
|
|
412
|
+
/**
|
|
413
|
+
* Hook to calculate cart total from items (client-side calculation).
|
|
414
|
+
* This is a quick calculation that doesn't account for server-side discounts.
|
|
415
|
+
*
|
|
416
|
+
* @returns The calculated total price
|
|
417
|
+
*
|
|
418
|
+
* @example
|
|
419
|
+
* ```tsx
|
|
420
|
+
* function CartSubtotal() {
|
|
421
|
+
* const total = useCartTotal();
|
|
422
|
+
* return <span>Subtotal: ${total.toFixed(2)}</span>;
|
|
423
|
+
* }
|
|
424
|
+
* ```
|
|
425
|
+
*/
|
|
426
|
+
declare const useCartTotal: () => number;
|
|
427
|
+
/**
|
|
428
|
+
* Hook to get the server-calculated total amount.
|
|
429
|
+
* This includes any discounts applied server-side.
|
|
430
|
+
*
|
|
431
|
+
* @returns The total amount object with amount and currencyCode, or undefined
|
|
432
|
+
*
|
|
433
|
+
* @example
|
|
434
|
+
* ```tsx
|
|
435
|
+
* function CartTotal() {
|
|
436
|
+
* const totalAmount = useCartTotalAmount();
|
|
437
|
+
* if (!totalAmount) return null;
|
|
438
|
+
* return <span>Total: {formatPrice(totalAmount.amount, totalAmount.currencyCode)}</span>;
|
|
439
|
+
* }
|
|
440
|
+
* ```
|
|
441
|
+
*/
|
|
442
|
+
declare const useCartTotalAmount: () => {
|
|
443
|
+
amount: number;
|
|
444
|
+
currencyCode: string;
|
|
445
|
+
} | undefined;
|
|
446
|
+
/**
|
|
447
|
+
* Hook to check if a product/variant is in the cart.
|
|
448
|
+
*
|
|
449
|
+
* @param productId - The product ID to check
|
|
450
|
+
* @param variantId - Optional variant ID for more specific check
|
|
451
|
+
* @returns True if the product (and optionally variant) is in the cart
|
|
452
|
+
*
|
|
453
|
+
* @example
|
|
454
|
+
* ```tsx
|
|
455
|
+
* function ProductCard({ product }) {
|
|
456
|
+
* const inCart = useIsInCart(product.id);
|
|
457
|
+
* return (
|
|
458
|
+
* <button disabled={inCart}>
|
|
459
|
+
* {inCart ? 'In Cart' : 'Add to Cart'}
|
|
460
|
+
* </button>
|
|
461
|
+
* );
|
|
462
|
+
* }
|
|
463
|
+
* ```
|
|
464
|
+
*/
|
|
465
|
+
declare const useIsInCart: (productId: string, variantId?: string) => boolean;
|
|
466
|
+
/**
|
|
467
|
+
* Hook to get a specific cart item by product/variant ID.
|
|
468
|
+
*
|
|
469
|
+
* @param productId - The product ID to find
|
|
470
|
+
* @param variantId - Optional variant ID for more specific search
|
|
471
|
+
* @returns The cart item if found, undefined otherwise
|
|
472
|
+
*
|
|
473
|
+
* @example
|
|
474
|
+
* ```tsx
|
|
475
|
+
* function ProductQuantity({ productId }) {
|
|
476
|
+
* const item = useCartItem(productId);
|
|
477
|
+
* return item ? <span>Qty: {item.quantity}</span> : null;
|
|
478
|
+
* }
|
|
479
|
+
* ```
|
|
480
|
+
*/
|
|
481
|
+
declare const useCartItem: (productId: string, variantId?: string) => CartItem | undefined;
|
|
482
|
+
/**
|
|
483
|
+
* Hook to get the checkout URL.
|
|
484
|
+
*
|
|
485
|
+
* @returns The checkout URL or undefined
|
|
486
|
+
*
|
|
487
|
+
* @example
|
|
488
|
+
* ```tsx
|
|
489
|
+
* function CheckoutButton() {
|
|
490
|
+
* const checkoutUrl = useCheckoutUrl();
|
|
491
|
+
* return checkoutUrl ? (
|
|
492
|
+
* <a href={checkoutUrl}>Proceed to Checkout</a>
|
|
493
|
+
* ) : null;
|
|
494
|
+
* }
|
|
495
|
+
* ```
|
|
496
|
+
*/
|
|
497
|
+
declare const useCheckoutUrl: () => string | undefined;
|
|
498
|
+
|
|
499
|
+
interface UseAddToCartOptions {
|
|
500
|
+
onSuccess?: (item: CartItem) => void;
|
|
501
|
+
onError?: (error: Error) => void;
|
|
502
|
+
defaultCurrencyCode?: string;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Hook for adding products to the cart with loading state management.
|
|
506
|
+
*/
|
|
507
|
+
declare function useAddToCart(options?: UseAddToCartOptions): {
|
|
508
|
+
addToCart: (product: any, variantId?: string, customQuantity?: number) => Promise<void>;
|
|
509
|
+
loadingStates: Record<string, boolean>;
|
|
510
|
+
isLoading: (productId: string) => boolean;
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Default cart service implementation using fetch API.
|
|
515
|
+
* Makes HTTP requests to cart API endpoints.
|
|
516
|
+
*/
|
|
517
|
+
declare class DefaultCartService implements ICartService {
|
|
518
|
+
private baseUrl;
|
|
519
|
+
constructor(baseUrl?: string);
|
|
520
|
+
private makeRequest;
|
|
521
|
+
private handleResponse;
|
|
522
|
+
createCart(merchantName: string): Promise<CartResponse>;
|
|
523
|
+
getCart(cartId: string): Promise<CartResponse>;
|
|
524
|
+
addToCart(cartId: string, items: CartItemRequest[]): Promise<void>;
|
|
525
|
+
removeFromCart(cartId: string, itemIds: string[]): Promise<void>;
|
|
526
|
+
updateCart(cartId: string, items: CartItemRequest[]): Promise<void>;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Default cart storage implementation using localStorage.
|
|
531
|
+
* Provides namespaced storage for multi-tenant support.
|
|
532
|
+
*/
|
|
533
|
+
declare class DefaultCartStorage implements ICartStorage {
|
|
534
|
+
private merchantName;
|
|
535
|
+
constructor(merchantName?: string);
|
|
536
|
+
private getStorageKey;
|
|
537
|
+
private get;
|
|
538
|
+
private set;
|
|
539
|
+
private remove;
|
|
540
|
+
getCartId(): string | null;
|
|
541
|
+
setCartId(cartId: string): void;
|
|
542
|
+
removeCartId(): void;
|
|
543
|
+
clear(): void;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Data-Layer Cart Service
|
|
548
|
+
*
|
|
549
|
+
* Adapter that bridges the cart package with @shopkit/data-layer.
|
|
550
|
+
* This allows cart operations to use the unified data-layer client
|
|
551
|
+
* instead of making direct HTTP calls.
|
|
552
|
+
*
|
|
553
|
+
* @module services/data-layer-cart-service
|
|
554
|
+
*/
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* Data-layer response interface (matches @shopkit/data-layer IResponse)
|
|
558
|
+
*/
|
|
559
|
+
interface DataLayerResponse<T = any> {
|
|
560
|
+
success: boolean;
|
|
561
|
+
message: string;
|
|
562
|
+
data: T | null;
|
|
563
|
+
error?: any;
|
|
564
|
+
meta?: any;
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* Data-layer client interface (cart methods only)
|
|
568
|
+
* This interface matches the cart-related methods from @shopkit/data-layer ICommerceClient
|
|
569
|
+
*/
|
|
570
|
+
interface IDataLayerClient {
|
|
571
|
+
getCart(params: {
|
|
572
|
+
id: string;
|
|
573
|
+
}, options?: any): Promise<DataLayerResponse>;
|
|
574
|
+
createCart(options?: any): Promise<DataLayerResponse>;
|
|
575
|
+
addToCart(params: {
|
|
576
|
+
id: string;
|
|
577
|
+
items: any[];
|
|
578
|
+
}, options?: any): Promise<DataLayerResponse>;
|
|
579
|
+
removeFromCart(params: {
|
|
580
|
+
id: string;
|
|
581
|
+
itemIds: string[];
|
|
582
|
+
}, options?: any): Promise<DataLayerResponse>;
|
|
583
|
+
updateCart(params: {
|
|
584
|
+
id: string;
|
|
585
|
+
items: any[];
|
|
586
|
+
}, options?: any): Promise<DataLayerResponse>;
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Cart service that uses @shopkit/data-layer for cart operations.
|
|
590
|
+
*
|
|
591
|
+
* This adapter bridges the cart package with the data-layer, allowing
|
|
592
|
+
* all cart operations to go through the unified commerce abstraction.
|
|
593
|
+
*
|
|
594
|
+
* @example
|
|
595
|
+
* ```typescript
|
|
596
|
+
* import { DataLayerCartService } from "@shopkit/cart";
|
|
597
|
+
* import { createCommerceClient } from "@shopkit/data-layer";
|
|
598
|
+
*
|
|
599
|
+
* const dataLayerClient = createCommerceClient({
|
|
600
|
+
* type: "shopify",
|
|
601
|
+
* config: { domain: "...", storefrontAccessToken: "..." }
|
|
602
|
+
* });
|
|
603
|
+
*
|
|
604
|
+
* const cartService = new DataLayerCartService(dataLayerClient);
|
|
605
|
+
*
|
|
606
|
+
* configureCart({
|
|
607
|
+
* merchantName: "my-store",
|
|
608
|
+
* cartService,
|
|
609
|
+
* cartStorage: new DefaultCartStorage("my-store"),
|
|
610
|
+
* });
|
|
611
|
+
* ```
|
|
612
|
+
*/
|
|
613
|
+
declare class DataLayerCartService implements ICartService {
|
|
614
|
+
private client;
|
|
615
|
+
constructor(dataLayerClient: IDataLayerClient);
|
|
616
|
+
/**
|
|
617
|
+
* Unwrap a data-layer response to get the raw data
|
|
618
|
+
* @throws Error if the response indicates failure
|
|
619
|
+
*/
|
|
620
|
+
private unwrapResponse;
|
|
621
|
+
/**
|
|
622
|
+
* Create a new cart
|
|
623
|
+
*/
|
|
624
|
+
createCart(merchantName: string): Promise<CartResponse>;
|
|
625
|
+
/**
|
|
626
|
+
* Get an existing cart by ID
|
|
627
|
+
*/
|
|
628
|
+
getCart(cartId: string): Promise<CartResponse>;
|
|
629
|
+
/**
|
|
630
|
+
* Add items to cart
|
|
631
|
+
*/
|
|
632
|
+
addToCart(cartId: string, items: CartItemRequest[]): Promise<void>;
|
|
633
|
+
/**
|
|
634
|
+
* Remove items from cart
|
|
635
|
+
*/
|
|
636
|
+
removeFromCart(cartId: string, itemIds: string[]): Promise<void>;
|
|
637
|
+
/**
|
|
638
|
+
* Update cart items
|
|
639
|
+
*/
|
|
640
|
+
updateCart(cartId: string, items: CartItemRequest[]): Promise<void>;
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* Type guard to check if a client is a data-layer client
|
|
644
|
+
*/
|
|
645
|
+
declare function isDataLayerClient(client: any): client is IDataLayerClient;
|
|
646
|
+
|
|
647
|
+
/**
|
|
648
|
+
* Maps a product object to a CartItem.
|
|
649
|
+
* Handles variant selection, price normalization, and currency fallback.
|
|
650
|
+
*/
|
|
651
|
+
declare function mapProductToCartItem(product: any, variantId?: string, quantity?: number, defaultCurrencyCode?: string): CartItem;
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* Format a price amount for display using Intl.NumberFormat.
|
|
655
|
+
*
|
|
656
|
+
* @param amount - The numeric price amount
|
|
657
|
+
* @param currencyCode - ISO 4217 currency code (default: "USD")
|
|
658
|
+
* @param locale - BCP 47 locale string (default: browser locale)
|
|
659
|
+
* @returns Formatted price string
|
|
660
|
+
*
|
|
661
|
+
* @example
|
|
662
|
+
* ```typescript
|
|
663
|
+
* formatPrice(29.99, "USD"); // "$29.99"
|
|
664
|
+
* formatPrice(29.99, "EUR", "de-DE"); // "29,99 €"
|
|
665
|
+
* formatPrice(1999, "INR", "en-IN"); // "₹1,999.00"
|
|
666
|
+
* ```
|
|
667
|
+
*/
|
|
668
|
+
declare function formatPrice(amount: number, currencyCode?: string, locale?: string): string;
|
|
669
|
+
/**
|
|
670
|
+
* Calculate the total price of cart items.
|
|
671
|
+
* Multiplies each item's price by its quantity and sums the results.
|
|
672
|
+
*
|
|
673
|
+
* @param items - Array of items with price and quantity
|
|
674
|
+
* @returns The total price
|
|
675
|
+
*
|
|
676
|
+
* @example
|
|
677
|
+
* ```typescript
|
|
678
|
+
* const items = [
|
|
679
|
+
* { price: { amount: 10 }, quantity: 2 },
|
|
680
|
+
* { price: { amount: 25 }, quantity: 1 },
|
|
681
|
+
* ];
|
|
682
|
+
* calculateCartTotal(items); // 45
|
|
683
|
+
* ```
|
|
684
|
+
*/
|
|
685
|
+
declare function calculateCartTotal(items: Array<{
|
|
686
|
+
price: number | {
|
|
687
|
+
amount: number;
|
|
688
|
+
};
|
|
689
|
+
quantity: number;
|
|
690
|
+
}>): number;
|
|
691
|
+
/**
|
|
692
|
+
* Calculate total savings from compareAtPrice vs price.
|
|
693
|
+
* Useful for displaying "You save X" on cart/checkout.
|
|
694
|
+
*
|
|
695
|
+
* @param items - Array of items with price, compareAtPrice, and quantity
|
|
696
|
+
* @returns The total savings amount
|
|
697
|
+
*
|
|
698
|
+
* @example
|
|
699
|
+
* ```typescript
|
|
700
|
+
* const items = [
|
|
701
|
+
* { price: { amount: 20 }, compareAtPrice: { amount: 30 }, quantity: 2 },
|
|
702
|
+
* ];
|
|
703
|
+
* calculateSavings(items); // 20 (saved $10 x 2 items)
|
|
704
|
+
* ```
|
|
705
|
+
*/
|
|
706
|
+
declare function calculateSavings(items: Array<{
|
|
707
|
+
price: number | {
|
|
708
|
+
amount: number;
|
|
709
|
+
};
|
|
710
|
+
compareAtPrice?: number | {
|
|
711
|
+
amount: number;
|
|
712
|
+
};
|
|
713
|
+
quantity: number;
|
|
714
|
+
}>): number;
|
|
715
|
+
|
|
716
|
+
interface CartInitializerProps {
|
|
717
|
+
merchantName: string;
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Cart initializer component.
|
|
721
|
+
*
|
|
722
|
+
* IMPORTANT: `configureCart()` must be called before this component mounts.
|
|
723
|
+
* Apps should either:
|
|
724
|
+
* 1. Call `configureCart()` at module scope in a client entry point, or
|
|
725
|
+
* 2. Create a wrapper component that calls `configureCart()` in a useEffect
|
|
726
|
+
* before rendering `<CartInitializer>`.
|
|
727
|
+
*/
|
|
728
|
+
declare function CartInitializer({ merchantName }: CartInitializerProps): null;
|
|
729
|
+
|
|
730
|
+
export { type CartActions, type CartConfig, type CartEvent, CartInitializer, type CartItem, type CartItemRequest, type CartResponse, type CartState, DataLayerCartService, DefaultCartService, DefaultCartStorage, type ICartService, type ICartStorage, type IDataLayerClient, type UseAddToCartOptions, calculateCartTotal, calculateSavings, configureCart, formatPrice, getCartConfig, isCartConfigured, isDataLayerClient, mapProductToCartItem, useAddToCart, useCartCount, useCartItem, useCartItems, useCartStatus, useCartStore, useCartToggle, useCartTotal, useCartTotalAmount, useCartTotalQuantity, useCheckoutUrl, useIsInCart };
|