@commercengine/react 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/README.md +358 -0
- package/dist/index.cjs +132 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +153 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +153 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +132 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
# @commercengine/react
|
|
2
|
+
|
|
3
|
+
React hook for Commerce Engine checkout.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @commercengine/react
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { useCheckout } from "@commercengine/react";
|
|
15
|
+
|
|
16
|
+
function App() {
|
|
17
|
+
const { openCart, cartCount, isReady } = useCheckout({
|
|
18
|
+
storeId: "store_xxx",
|
|
19
|
+
apiKey: "ak_xxx",
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<button onClick={openCart} disabled={!isReady}>
|
|
24
|
+
Cart ({cartCount})
|
|
25
|
+
</button>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Configuration
|
|
31
|
+
|
|
32
|
+
### UseCheckoutOptions
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
interface UseCheckoutOptions {
|
|
36
|
+
// === Credentials (required) ===
|
|
37
|
+
storeId: string; // Your Commerce Engine Store ID
|
|
38
|
+
apiKey: string; // Your Commerce Engine API Key
|
|
39
|
+
|
|
40
|
+
// === Development ===
|
|
41
|
+
url?: string; // Direct checkout URL (local dev only)
|
|
42
|
+
|
|
43
|
+
// === Theme ===
|
|
44
|
+
theme?: "light" | "dark" | "system"; // Default: "system"
|
|
45
|
+
|
|
46
|
+
// === Appearance ===
|
|
47
|
+
zIndex?: number; // Overlay z-index. Default: 99999
|
|
48
|
+
|
|
49
|
+
// === Authentication ===
|
|
50
|
+
authMode?: "managed" | "provided"; // Default: "managed"
|
|
51
|
+
accessToken?: string; // Initial access token
|
|
52
|
+
refreshToken?: string; // Initial refresh token
|
|
53
|
+
|
|
54
|
+
// === Quick Buy ===
|
|
55
|
+
quickBuy?: {
|
|
56
|
+
productId: string; // Product ID (required)
|
|
57
|
+
variantId: string | null; // Variant ID (required, null for non-variant)
|
|
58
|
+
quantity?: number; // Default: 1
|
|
59
|
+
};
|
|
60
|
+
sessionMode?: "continue-existing" | "force-new"; // Default: "continue-existing"
|
|
61
|
+
autoDetectQuickBuy?: boolean; // Auto-detect from parent URL. Default: false
|
|
62
|
+
|
|
63
|
+
// === Callbacks ===
|
|
64
|
+
onReady?: () => void;
|
|
65
|
+
onOpen?: () => void;
|
|
66
|
+
onClose?: () => void;
|
|
67
|
+
onComplete?: (order: OrderData) => void;
|
|
68
|
+
onCartUpdate?: (cart: CartData) => void;
|
|
69
|
+
onAuthChange?: (auth: AuthChangeData) => void;
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Session Modes:**
|
|
74
|
+
- **`continue-existing`** (default): Add quick-buy item to existing cart
|
|
75
|
+
- **`force-new`**: Delete existing cart and start fresh with only the quick-buy item
|
|
76
|
+
|
|
77
|
+
**Note:** When quick buy params are provided (via config or auto-detected), the cart drawer automatically opens once checkout is ready.
|
|
78
|
+
|
|
79
|
+
### Example: Full Configuration
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
import { useCheckout } from "@commercengine/react";
|
|
83
|
+
|
|
84
|
+
function Store() {
|
|
85
|
+
const {
|
|
86
|
+
openCart,
|
|
87
|
+
openCheckout,
|
|
88
|
+
close,
|
|
89
|
+
updateTokens,
|
|
90
|
+
isReady,
|
|
91
|
+
isOpen,
|
|
92
|
+
cartCount,
|
|
93
|
+
cartTotal,
|
|
94
|
+
cartCurrency,
|
|
95
|
+
} = useCheckout({
|
|
96
|
+
storeId: "store_xxx",
|
|
97
|
+
apiKey: "ak_xxx",
|
|
98
|
+
theme: "dark",
|
|
99
|
+
zIndex: 100000,
|
|
100
|
+
accessToken: session?.accessToken,
|
|
101
|
+
refreshToken: session?.refreshToken,
|
|
102
|
+
onReady: () => {
|
|
103
|
+
console.log("Checkout ready");
|
|
104
|
+
},
|
|
105
|
+
onComplete: (order) => {
|
|
106
|
+
router.push(`/thank-you?order=${order.orderNumber}`);
|
|
107
|
+
},
|
|
108
|
+
onCartUpdate: (cart) => {
|
|
109
|
+
console.log("Cart updated:", cart.count, cart.total);
|
|
110
|
+
},
|
|
111
|
+
onAuthChange: ({ type, accessToken }) => {
|
|
112
|
+
if (type === "login") {
|
|
113
|
+
// Sync to your auth system
|
|
114
|
+
setSession({ accessToken });
|
|
115
|
+
} else if (type === "logout") {
|
|
116
|
+
setSession(null);
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
return (
|
|
122
|
+
<nav>
|
|
123
|
+
<button onClick={openCart} disabled={!isReady}>
|
|
124
|
+
Cart ({cartCount}) - {cartCurrency} {cartTotal}
|
|
125
|
+
</button>
|
|
126
|
+
</nav>
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Return Value
|
|
132
|
+
|
|
133
|
+
### UseCheckoutReturn
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
interface UseCheckoutReturn {
|
|
137
|
+
// === Methods ===
|
|
138
|
+
openCart: () => void; // Open cart drawer
|
|
139
|
+
openCheckout: () => void; // Open checkout directly (Buy Now)
|
|
140
|
+
close: () => void; // Close overlay
|
|
141
|
+
updateTokens: ( // Sync auth state
|
|
142
|
+
accessToken: string,
|
|
143
|
+
refreshToken?: string
|
|
144
|
+
) => void;
|
|
145
|
+
addToCart: ( // Add item to cart and open cart drawer
|
|
146
|
+
productId: string,
|
|
147
|
+
variantId: string | null,
|
|
148
|
+
quantity?: number
|
|
149
|
+
) => void;
|
|
150
|
+
|
|
151
|
+
// === State ===
|
|
152
|
+
isReady: boolean; // Checkout initialized
|
|
153
|
+
isOpen: boolean; // Overlay visible
|
|
154
|
+
cartCount: number; // Items in cart
|
|
155
|
+
cartTotal: number; // Cart subtotal
|
|
156
|
+
cartCurrency: string; // Currency code (e.g., "USD")
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Examples
|
|
161
|
+
|
|
162
|
+
### Cart Button with Badge
|
|
163
|
+
|
|
164
|
+
```tsx
|
|
165
|
+
function CartButton() {
|
|
166
|
+
const { openCart, cartCount, isReady } = useCheckout({
|
|
167
|
+
storeId: "store_xxx",
|
|
168
|
+
apiKey: "ak_xxx",
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
return (
|
|
172
|
+
<button onClick={openCart} disabled={!isReady}>
|
|
173
|
+
<ShoppingCart />
|
|
174
|
+
{cartCount > 0 && <span className="badge">{cartCount}</span>}
|
|
175
|
+
</button>
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Add to Cart
|
|
181
|
+
|
|
182
|
+
```tsx
|
|
183
|
+
function ProductCard({ product }: { product: Product }) {
|
|
184
|
+
const { addToCart, isReady } = useCheckout({
|
|
185
|
+
storeId: "store_xxx",
|
|
186
|
+
apiKey: "ak_xxx",
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
const handleAddToCart = () => {
|
|
190
|
+
// variantId is required - use null for non-variant products
|
|
191
|
+
// Cart drawer opens automatically after adding
|
|
192
|
+
addToCart(product.id, product.variantId ?? null, 1);
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
return (
|
|
196
|
+
<div>
|
|
197
|
+
<h3>{product.name}</h3>
|
|
198
|
+
<button onClick={handleAddToCart} disabled={!isReady}>
|
|
199
|
+
Add to Cart
|
|
200
|
+
</button>
|
|
201
|
+
</div>
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Buy Now Button
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
function BuyNowButton({ productId, variantId }: { productId: string; variantId: string | null }) {
|
|
210
|
+
const { addToCart, openCheckout, isReady } = useCheckout({
|
|
211
|
+
storeId: "store_xxx",
|
|
212
|
+
apiKey: "ak_xxx",
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
const handleBuyNow = () => {
|
|
216
|
+
addToCart(productId, variantId, 1);
|
|
217
|
+
openCheckout();
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
return (
|
|
221
|
+
<button onClick={handleBuyNow} disabled={!isReady}>
|
|
222
|
+
Buy Now
|
|
223
|
+
</button>
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Order Completion with Redirect
|
|
229
|
+
|
|
230
|
+
```tsx
|
|
231
|
+
function CheckoutButton() {
|
|
232
|
+
const router = useRouter();
|
|
233
|
+
|
|
234
|
+
const { openCart, isReady } = useCheckout({
|
|
235
|
+
storeId: "store_xxx",
|
|
236
|
+
apiKey: "ak_xxx",
|
|
237
|
+
onComplete: (order) => {
|
|
238
|
+
// Redirect to thank you page
|
|
239
|
+
router.push(`/order/${order.orderNumber}`);
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
return (
|
|
244
|
+
<button onClick={openCart} disabled={!isReady}>
|
|
245
|
+
Checkout
|
|
246
|
+
</button>
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Syncing Authentication
|
|
252
|
+
|
|
253
|
+
```tsx
|
|
254
|
+
function App() {
|
|
255
|
+
const [session, setSession] = useState(null);
|
|
256
|
+
|
|
257
|
+
const { updateTokens, openCart } = useCheckout({
|
|
258
|
+
storeId: "store_xxx",
|
|
259
|
+
apiKey: "ak_xxx",
|
|
260
|
+
// Pass initial tokens
|
|
261
|
+
accessToken: session?.accessToken,
|
|
262
|
+
refreshToken: session?.refreshToken,
|
|
263
|
+
// Sync when user logs in via checkout
|
|
264
|
+
onAuthChange: ({ type, accessToken, refreshToken }) => {
|
|
265
|
+
if (type === "login") {
|
|
266
|
+
setSession({ accessToken, refreshToken });
|
|
267
|
+
} else if (type === "logout") {
|
|
268
|
+
setSession(null);
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
// Sync when user logs in on your site
|
|
274
|
+
const handleLogin = async (credentials) => {
|
|
275
|
+
const tokens = await login(credentials);
|
|
276
|
+
setSession(tokens);
|
|
277
|
+
updateTokens(tokens.accessToken, tokens.refreshToken);
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
// Sync when user logs out on your site
|
|
281
|
+
const handleLogout = () => {
|
|
282
|
+
setSession(null);
|
|
283
|
+
updateTokens("", "");
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
return (
|
|
287
|
+
<div>
|
|
288
|
+
{session ? (
|
|
289
|
+
<button onClick={handleLogout}>Logout</button>
|
|
290
|
+
) : (
|
|
291
|
+
<button onClick={() => handleLogin({ ... })}>Login</button>
|
|
292
|
+
)}
|
|
293
|
+
<button onClick={openCart}>Cart</button>
|
|
294
|
+
</div>
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Mini Cart Display
|
|
300
|
+
|
|
301
|
+
```tsx
|
|
302
|
+
function MiniCart() {
|
|
303
|
+
const { openCart, cartCount, cartTotal, cartCurrency, isReady } = useCheckout({
|
|
304
|
+
storeId: "store_xxx",
|
|
305
|
+
apiKey: "ak_xxx",
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
if (!isReady) {
|
|
309
|
+
return <div>Loading...</div>;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return (
|
|
313
|
+
<div className="mini-cart" onClick={openCart}>
|
|
314
|
+
<span>{cartCount} items</span>
|
|
315
|
+
<span>{cartCurrency} {cartTotal.toFixed(2)}</span>
|
|
316
|
+
</div>
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
## Hook Lifecycle
|
|
322
|
+
|
|
323
|
+
The hook:
|
|
324
|
+
1. Creates checkout iframe on mount
|
|
325
|
+
2. Destroys iframe on unmount
|
|
326
|
+
3. Reinitializes when `url`, `storeId`, or `apiKey` change
|
|
327
|
+
4. Other options (theme, callbacks, tokens) update without reinitializing
|
|
328
|
+
|
|
329
|
+
```tsx
|
|
330
|
+
// This will NOT cause reinit (callbacks stored in ref)
|
|
331
|
+
const { openCart } = useCheckout({
|
|
332
|
+
storeId: "store_xxx",
|
|
333
|
+
apiKey: "ak_xxx",
|
|
334
|
+
onComplete: (order) => {
|
|
335
|
+
// Safe to use state/props here - always uses latest values
|
|
336
|
+
doSomething(currentState);
|
|
337
|
+
},
|
|
338
|
+
});
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## TypeScript
|
|
342
|
+
|
|
343
|
+
Types are re-exported from `@commercengine/js`:
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
import {
|
|
347
|
+
useCheckout,
|
|
348
|
+
type UseCheckoutOptions,
|
|
349
|
+
type UseCheckoutReturn,
|
|
350
|
+
type CartData,
|
|
351
|
+
type OrderData,
|
|
352
|
+
type AuthChangeData,
|
|
353
|
+
} from "@commercengine/react";
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
## Peer Dependencies
|
|
357
|
+
|
|
358
|
+
- `react` >= 17.0.0
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
let _commercengine_js = require("@commercengine/js");
|
|
2
|
+
let react = require("react");
|
|
3
|
+
|
|
4
|
+
//#region src/use-checkout.ts
|
|
5
|
+
/**
|
|
6
|
+
* useCheckout Hook
|
|
7
|
+
*
|
|
8
|
+
* React hook for Commerce Engine Checkout integration.
|
|
9
|
+
* Handles checkout initialization, state management, and cleanup.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* import { useCheckout } from "@commercengine/react";
|
|
14
|
+
*
|
|
15
|
+
* function MyStore() {
|
|
16
|
+
* const { openCart, openCheckout, cartCount, isReady } = useCheckout({
|
|
17
|
+
* storeId: "store_xxx",
|
|
18
|
+
* apiKey: "ak_xxx",
|
|
19
|
+
* theme: "dark",
|
|
20
|
+
* onComplete: (order) => {
|
|
21
|
+
* console.log("Order placed:", order.orderNumber);
|
|
22
|
+
* window.location.href = "/thank-you";
|
|
23
|
+
* },
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* return (
|
|
27
|
+
* <button onClick={openCart} disabled={!isReady}>
|
|
28
|
+
* Cart ({cartCount})
|
|
29
|
+
* </button>
|
|
30
|
+
* );
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
/**
|
|
35
|
+
* React hook for Commerce Engine Checkout
|
|
36
|
+
*
|
|
37
|
+
* @param options - Checkout configuration
|
|
38
|
+
* @returns Checkout state and methods
|
|
39
|
+
*/
|
|
40
|
+
function useCheckout(options) {
|
|
41
|
+
const checkoutRef = (0, react.useRef)(null);
|
|
42
|
+
const [isReady, setIsReady] = (0, react.useState)(false);
|
|
43
|
+
const [isOpen, setIsOpen] = (0, react.useState)(false);
|
|
44
|
+
const [cart, setCart] = (0, react.useState)({
|
|
45
|
+
count: 0,
|
|
46
|
+
total: 0,
|
|
47
|
+
currency: "INR"
|
|
48
|
+
});
|
|
49
|
+
const optionsRef = (0, react.useRef)(options);
|
|
50
|
+
optionsRef.current = options;
|
|
51
|
+
const { url, storeId, apiKey } = options;
|
|
52
|
+
(0, react.useEffect)(() => {
|
|
53
|
+
if (typeof window === "undefined") return;
|
|
54
|
+
const opts = optionsRef.current;
|
|
55
|
+
const checkout = new _commercengine_js.Checkout({
|
|
56
|
+
url,
|
|
57
|
+
storeId,
|
|
58
|
+
apiKey,
|
|
59
|
+
theme: opts.theme,
|
|
60
|
+
authMode: opts.authMode,
|
|
61
|
+
accessToken: opts.accessToken,
|
|
62
|
+
refreshToken: opts.refreshToken,
|
|
63
|
+
quickBuy: opts.quickBuy,
|
|
64
|
+
sessionMode: opts.sessionMode,
|
|
65
|
+
autoDetectQuickBuy: opts.autoDetectQuickBuy,
|
|
66
|
+
appearance: { zIndex: opts.zIndex },
|
|
67
|
+
onReady: () => {
|
|
68
|
+
setIsReady(true);
|
|
69
|
+
optionsRef.current.onReady?.();
|
|
70
|
+
},
|
|
71
|
+
onOpen: () => {
|
|
72
|
+
setIsOpen(true);
|
|
73
|
+
optionsRef.current.onOpen?.();
|
|
74
|
+
},
|
|
75
|
+
onClose: () => {
|
|
76
|
+
setIsOpen(false);
|
|
77
|
+
optionsRef.current.onClose?.();
|
|
78
|
+
},
|
|
79
|
+
onComplete: (order) => {
|
|
80
|
+
optionsRef.current.onComplete?.(order);
|
|
81
|
+
},
|
|
82
|
+
onCartUpdate: (cartData) => {
|
|
83
|
+
setCart(cartData);
|
|
84
|
+
optionsRef.current.onCartUpdate?.(cartData);
|
|
85
|
+
},
|
|
86
|
+
onAuthChange: (auth) => {
|
|
87
|
+
optionsRef.current.onAuthChange?.(auth);
|
|
88
|
+
},
|
|
89
|
+
onError: (error) => {
|
|
90
|
+
setIsReady(true);
|
|
91
|
+
optionsRef.current.onError?.(error);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
checkoutRef.current = checkout;
|
|
95
|
+
return () => {
|
|
96
|
+
checkout.destroy();
|
|
97
|
+
checkoutRef.current = null;
|
|
98
|
+
setIsReady(false);
|
|
99
|
+
setIsOpen(false);
|
|
100
|
+
};
|
|
101
|
+
}, [
|
|
102
|
+
url,
|
|
103
|
+
storeId,
|
|
104
|
+
apiKey
|
|
105
|
+
]);
|
|
106
|
+
return {
|
|
107
|
+
openCart: (0, react.useCallback)(() => {
|
|
108
|
+
checkoutRef.current?.openCart();
|
|
109
|
+
}, []),
|
|
110
|
+
openCheckout: (0, react.useCallback)(() => {
|
|
111
|
+
checkoutRef.current?.openCheckout();
|
|
112
|
+
}, []),
|
|
113
|
+
close: (0, react.useCallback)(() => {
|
|
114
|
+
checkoutRef.current?.close();
|
|
115
|
+
}, []),
|
|
116
|
+
updateTokens: (0, react.useCallback)((accessToken, refreshToken) => {
|
|
117
|
+
checkoutRef.current?.updateTokens(accessToken, refreshToken);
|
|
118
|
+
}, []),
|
|
119
|
+
addToCart: (0, react.useCallback)((productId, variantId, quantity) => {
|
|
120
|
+
checkoutRef.current?.addToCart(productId, variantId, quantity);
|
|
121
|
+
}, []),
|
|
122
|
+
isReady,
|
|
123
|
+
isOpen,
|
|
124
|
+
cartCount: cart.count,
|
|
125
|
+
cartTotal: cart.total,
|
|
126
|
+
cartCurrency: cart.currency
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
//#endregion
|
|
131
|
+
exports.useCheckout = useCheckout;
|
|
132
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["Checkout"],"sources":["../src/use-checkout.ts"],"sourcesContent":["/**\n * useCheckout Hook\n *\n * React hook for Commerce Engine Checkout integration.\n * Handles checkout initialization, state management, and cleanup.\n *\n * @example\n * ```tsx\n * import { useCheckout } from \"@commercengine/react\";\n *\n * function MyStore() {\n * const { openCart, openCheckout, cartCount, isReady } = useCheckout({\n * storeId: \"store_xxx\",\n * apiKey: \"ak_xxx\",\n * theme: \"dark\",\n * onComplete: (order) => {\n * console.log(\"Order placed:\", order.orderNumber);\n * window.location.href = \"/thank-you\";\n * },\n * });\n *\n * return (\n * <button onClick={openCart} disabled={!isReady}>\n * Cart ({cartCount})\n * </button>\n * );\n * }\n * ```\n */\n\nimport {\n type AuthChangeData,\n type AuthMode,\n type CartData,\n Checkout,\n type CheckoutConfig,\n type ErrorData,\n type OrderData,\n type QuickBuyConfig,\n type SessionMode,\n} from \"@commercengine/js\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/**\n * Options for useCheckout hook\n */\nexport interface UseCheckoutOptions {\n /**\n * Your Commerce Engine Store ID\n * @example \"store_abc123\"\n */\n storeId?: string;\n\n /**\n * Your Commerce Engine API Key\n * @example \"ak_test_xyz789\"\n */\n apiKey?: string;\n\n /**\n * Checkout URL for local development\n * In production, URL is resolved from storeId/apiKey\n */\n url?: string;\n\n /**\n * Theme preference\n * @default \"system\"\n */\n theme?: \"light\" | \"dark\" | \"system\";\n\n /**\n * Z-index for the checkout overlay\n * @default 99999\n */\n zIndex?: number;\n\n /**\n * Authentication mode\n * - 'managed': Checkout manages token lifecycle (default)\n * - 'provided': Parent manages tokens, checkout uses in-memory only\n * @default \"managed\"\n */\n authMode?: AuthMode;\n\n /**\n * Initial access token (if user already logged in)\n */\n accessToken?: string;\n\n /**\n * Initial refresh token\n */\n refreshToken?: string;\n\n /**\n * Quick buy configuration for \"Buy Now\" flows\n * When provided, adds the product to cart on initialization\n */\n quickBuy?: QuickBuyConfig;\n\n /**\n * Session behavior when quick buy is used\n * @default \"continue-existing\"\n */\n sessionMode?: SessionMode;\n\n /**\n * Auto-detect quick buy params from parent page URL\n * When enabled, SDK parses window.location.search for:\n * - product_id, variant_id, qty/quantity, session_mode\n * Useful for ad-driven traffic to embedded checkout pages\n * @default false\n */\n autoDetectQuickBuy?: boolean;\n\n /**\n * Called when checkout iframe is ready\n */\n onReady?: () => void;\n\n /**\n * Called when checkout is opened\n */\n onOpen?: () => void;\n\n /**\n * Called when checkout is closed\n */\n onClose?: () => void;\n\n /**\n * Called when order is completed\n */\n onComplete?: (order: OrderData) => void;\n\n /**\n * Called when cart state changes\n */\n onCartUpdate?: (cart: CartData) => void;\n\n /**\n * Called when auth state changes\n */\n onAuthChange?: (auth: AuthChangeData) => void;\n\n /**\n * Called when checkout encounters a configuration error\n */\n onError?: (error: ErrorData) => void;\n}\n\n/**\n * Return value from useCheckout hook\n */\nexport interface UseCheckoutReturn {\n /**\n * Open the cart drawer\n */\n openCart: () => void;\n\n /**\n * Open the checkout drawer directly (for Buy Now flow)\n */\n openCheckout: () => void;\n\n /**\n * Close the checkout overlay\n */\n close: () => void;\n\n /**\n * Update auth tokens (when user logs in/out on parent site)\n */\n updateTokens: (accessToken: string, refreshToken?: string) => void;\n\n /**\n * Add item to cart\n * @param productId - Product ID (required)\n * @param variantId - Variant ID (required, null for non-variant products)\n * @param quantity - Quantity to add (default: 1)\n */\n addToCart: (productId: string, variantId: string | null, quantity?: number) => void;\n\n /**\n * Whether checkout is ready to use\n */\n isReady: boolean;\n\n /**\n * Whether checkout overlay is currently open\n */\n isOpen: boolean;\n\n /**\n * Number of items in cart\n */\n cartCount: number;\n\n /**\n * Cart subtotal amount\n */\n cartTotal: number;\n\n /**\n * Cart currency code\n */\n cartCurrency: string;\n}\n\n// =============================================================================\n// HOOK\n// =============================================================================\n\n/**\n * React hook for Commerce Engine Checkout\n *\n * @param options - Checkout configuration\n * @returns Checkout state and methods\n */\nexport function useCheckout(options: UseCheckoutOptions): UseCheckoutReturn {\n const checkoutRef = useRef<Checkout | null>(null);\n const [isReady, setIsReady] = useState(false);\n const [isOpen, setIsOpen] = useState(false);\n const [cart, setCart] = useState<CartData>({ count: 0, total: 0, currency: \"INR\" });\n\n // Store options in ref to avoid recreating checkout on callback changes\n // This allows stable callbacks while still using latest callback values\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n // Destructure stable keys for dependency array\n const { url, storeId, apiKey } = options;\n\n // Initialize checkout on mount or when key config changes\n useEffect(() => {\n // Skip on server\n if (typeof window === \"undefined\") return;\n\n // Get current options from ref for non-key values\n const opts = optionsRef.current;\n\n const config: CheckoutConfig = {\n url,\n storeId,\n apiKey,\n theme: opts.theme,\n authMode: opts.authMode,\n accessToken: opts.accessToken,\n refreshToken: opts.refreshToken,\n quickBuy: opts.quickBuy,\n sessionMode: opts.sessionMode,\n autoDetectQuickBuy: opts.autoDetectQuickBuy,\n appearance: {\n zIndex: opts.zIndex,\n },\n onReady: () => {\n setIsReady(true);\n optionsRef.current.onReady?.();\n },\n onOpen: () => {\n setIsOpen(true);\n optionsRef.current.onOpen?.();\n },\n onClose: () => {\n setIsOpen(false);\n optionsRef.current.onClose?.();\n },\n onComplete: (order) => {\n optionsRef.current.onComplete?.(order);\n },\n onCartUpdate: (cartData) => {\n setCart(cartData);\n optionsRef.current.onCartUpdate?.(cartData);\n },\n onAuthChange: (auth) => {\n optionsRef.current.onAuthChange?.(auth);\n },\n onError: (error) => {\n // Still set ready so buttons are enabled (error drawer will show)\n setIsReady(true);\n optionsRef.current.onError?.(error);\n },\n };\n\n const checkout = new Checkout(config);\n checkoutRef.current = checkout;\n\n return () => {\n checkout.destroy();\n checkoutRef.current = null;\n setIsReady(false);\n setIsOpen(false);\n };\n // Only reinitialize when URL or credentials change\n // Other options like theme, tokens, callbacks are read from optionsRef\n }, [url, storeId, apiKey]);\n\n // Stable callback refs\n const openCart = useCallback(() => {\n checkoutRef.current?.openCart();\n }, []);\n\n const openCheckout = useCallback(() => {\n checkoutRef.current?.openCheckout();\n }, []);\n\n const close = useCallback(() => {\n checkoutRef.current?.close();\n }, []);\n\n const updateTokens = useCallback((accessToken: string, refreshToken?: string) => {\n checkoutRef.current?.updateTokens(accessToken, refreshToken);\n }, []);\n\n const addToCart = useCallback(\n (productId: string, variantId: string | null, quantity?: number) => {\n checkoutRef.current?.addToCart(productId, variantId, quantity);\n },\n []\n );\n\n return {\n openCart,\n openCheckout,\n close,\n updateTokens,\n addToCart,\n isReady,\n isOpen,\n cartCount: cart.count,\n cartTotal: cart.total,\n cartCurrency: cart.currency,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgOA,SAAgB,YAAY,SAAgD;CAC1E,MAAM,gCAAsC,KAAK;CACjD,MAAM,CAAC,SAAS,kCAAuB,MAAM;CAC7C,MAAM,CAAC,QAAQ,iCAAsB,MAAM;CAC3C,MAAM,CAAC,MAAM,+BAA8B;EAAE,OAAO;EAAG,OAAO;EAAG,UAAU;EAAO,CAAC;CAInF,MAAM,+BAAoB,QAAQ;AAClC,YAAW,UAAU;CAGrB,MAAM,EAAE,KAAK,SAAS,WAAW;AAGjC,4BAAgB;AAEd,MAAI,OAAO,WAAW,YAAa;EAGnC,MAAM,OAAO,WAAW;EA6CxB,MAAM,WAAW,IAAIA,2BA3CU;GAC7B;GACA;GACA;GACA,OAAO,KAAK;GACZ,UAAU,KAAK;GACf,aAAa,KAAK;GAClB,cAAc,KAAK;GACnB,UAAU,KAAK;GACf,aAAa,KAAK;GAClB,oBAAoB,KAAK;GACzB,YAAY,EACV,QAAQ,KAAK,QACd;GACD,eAAe;AACb,eAAW,KAAK;AAChB,eAAW,QAAQ,WAAW;;GAEhC,cAAc;AACZ,cAAU,KAAK;AACf,eAAW,QAAQ,UAAU;;GAE/B,eAAe;AACb,cAAU,MAAM;AAChB,eAAW,QAAQ,WAAW;;GAEhC,aAAa,UAAU;AACrB,eAAW,QAAQ,aAAa,MAAM;;GAExC,eAAe,aAAa;AAC1B,YAAQ,SAAS;AACjB,eAAW,QAAQ,eAAe,SAAS;;GAE7C,eAAe,SAAS;AACtB,eAAW,QAAQ,eAAe,KAAK;;GAEzC,UAAU,UAAU;AAElB,eAAW,KAAK;AAChB,eAAW,QAAQ,UAAU,MAAM;;GAEtC,CAEoC;AACrC,cAAY,UAAU;AAEtB,eAAa;AACX,YAAS,SAAS;AAClB,eAAY,UAAU;AACtB,cAAW,MAAM;AACjB,aAAU,MAAM;;IAIjB;EAAC;EAAK;EAAS;EAAO,CAAC;AA0B1B,QAAO;EACL,uCAxBiC;AACjC,eAAY,SAAS,UAAU;KAC9B,EAAE,CAAC;EAuBJ,2CArBqC;AACrC,eAAY,SAAS,cAAc;KAClC,EAAE,CAAC;EAoBJ,oCAlB8B;AAC9B,eAAY,SAAS,OAAO;KAC3B,EAAE,CAAC;EAiBJ,sCAfgC,aAAqB,iBAA0B;AAC/E,eAAY,SAAS,aAAa,aAAa,aAAa;KAC3D,EAAE,CAAC;EAcJ,mCAXC,WAAmB,WAA0B,aAAsB;AAClE,eAAY,SAAS,UAAU,WAAW,WAAW,SAAS;KAEhE,EAAE,CACH;EAQC;EACA;EACA,WAAW,KAAK;EAChB,WAAW,KAAK;EAChB,cAAc,KAAK;EACpB"}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { AddToCartItem, AuthChangeData, AuthChangeData as AuthChangeData$1, AuthMode, AuthMode as AuthMode$1, CartData, CartData as CartData$1, ErrorData, OrderData, OrderData as OrderData$1, QuickBuyConfig, QuickBuyConfig as QuickBuyConfig$1, SessionMode, SessionMode as SessionMode$1 } from "@commercengine/js";
|
|
2
|
+
|
|
3
|
+
//#region src/use-checkout.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Options for useCheckout hook
|
|
7
|
+
*/
|
|
8
|
+
interface UseCheckoutOptions {
|
|
9
|
+
/**
|
|
10
|
+
* Your Commerce Engine Store ID
|
|
11
|
+
* @example "store_abc123"
|
|
12
|
+
*/
|
|
13
|
+
storeId?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Your Commerce Engine API Key
|
|
16
|
+
* @example "ak_test_xyz789"
|
|
17
|
+
*/
|
|
18
|
+
apiKey?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Checkout URL for local development
|
|
21
|
+
* In production, URL is resolved from storeId/apiKey
|
|
22
|
+
*/
|
|
23
|
+
url?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Theme preference
|
|
26
|
+
* @default "system"
|
|
27
|
+
*/
|
|
28
|
+
theme?: "light" | "dark" | "system";
|
|
29
|
+
/**
|
|
30
|
+
* Z-index for the checkout overlay
|
|
31
|
+
* @default 99999
|
|
32
|
+
*/
|
|
33
|
+
zIndex?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Authentication mode
|
|
36
|
+
* - 'managed': Checkout manages token lifecycle (default)
|
|
37
|
+
* - 'provided': Parent manages tokens, checkout uses in-memory only
|
|
38
|
+
* @default "managed"
|
|
39
|
+
*/
|
|
40
|
+
authMode?: AuthMode$1;
|
|
41
|
+
/**
|
|
42
|
+
* Initial access token (if user already logged in)
|
|
43
|
+
*/
|
|
44
|
+
accessToken?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Initial refresh token
|
|
47
|
+
*/
|
|
48
|
+
refreshToken?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Quick buy configuration for "Buy Now" flows
|
|
51
|
+
* When provided, adds the product to cart on initialization
|
|
52
|
+
*/
|
|
53
|
+
quickBuy?: QuickBuyConfig$1;
|
|
54
|
+
/**
|
|
55
|
+
* Session behavior when quick buy is used
|
|
56
|
+
* @default "continue-existing"
|
|
57
|
+
*/
|
|
58
|
+
sessionMode?: SessionMode$1;
|
|
59
|
+
/**
|
|
60
|
+
* Auto-detect quick buy params from parent page URL
|
|
61
|
+
* When enabled, SDK parses window.location.search for:
|
|
62
|
+
* - product_id, variant_id, qty/quantity, session_mode
|
|
63
|
+
* Useful for ad-driven traffic to embedded checkout pages
|
|
64
|
+
* @default false
|
|
65
|
+
*/
|
|
66
|
+
autoDetectQuickBuy?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Called when checkout iframe is ready
|
|
69
|
+
*/
|
|
70
|
+
onReady?: () => void;
|
|
71
|
+
/**
|
|
72
|
+
* Called when checkout is opened
|
|
73
|
+
*/
|
|
74
|
+
onOpen?: () => void;
|
|
75
|
+
/**
|
|
76
|
+
* Called when checkout is closed
|
|
77
|
+
*/
|
|
78
|
+
onClose?: () => void;
|
|
79
|
+
/**
|
|
80
|
+
* Called when order is completed
|
|
81
|
+
*/
|
|
82
|
+
onComplete?: (order: OrderData$1) => void;
|
|
83
|
+
/**
|
|
84
|
+
* Called when cart state changes
|
|
85
|
+
*/
|
|
86
|
+
onCartUpdate?: (cart: CartData$1) => void;
|
|
87
|
+
/**
|
|
88
|
+
* Called when auth state changes
|
|
89
|
+
*/
|
|
90
|
+
onAuthChange?: (auth: AuthChangeData$1) => void;
|
|
91
|
+
/**
|
|
92
|
+
* Called when checkout encounters a configuration error
|
|
93
|
+
*/
|
|
94
|
+
onError?: (error: ErrorData) => void;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Return value from useCheckout hook
|
|
98
|
+
*/
|
|
99
|
+
interface UseCheckoutReturn {
|
|
100
|
+
/**
|
|
101
|
+
* Open the cart drawer
|
|
102
|
+
*/
|
|
103
|
+
openCart: () => void;
|
|
104
|
+
/**
|
|
105
|
+
* Open the checkout drawer directly (for Buy Now flow)
|
|
106
|
+
*/
|
|
107
|
+
openCheckout: () => void;
|
|
108
|
+
/**
|
|
109
|
+
* Close the checkout overlay
|
|
110
|
+
*/
|
|
111
|
+
close: () => void;
|
|
112
|
+
/**
|
|
113
|
+
* Update auth tokens (when user logs in/out on parent site)
|
|
114
|
+
*/
|
|
115
|
+
updateTokens: (accessToken: string, refreshToken?: string) => void;
|
|
116
|
+
/**
|
|
117
|
+
* Add item to cart
|
|
118
|
+
* @param productId - Product ID (required)
|
|
119
|
+
* @param variantId - Variant ID (required, null for non-variant products)
|
|
120
|
+
* @param quantity - Quantity to add (default: 1)
|
|
121
|
+
*/
|
|
122
|
+
addToCart: (productId: string, variantId: string | null, quantity?: number) => void;
|
|
123
|
+
/**
|
|
124
|
+
* Whether checkout is ready to use
|
|
125
|
+
*/
|
|
126
|
+
isReady: boolean;
|
|
127
|
+
/**
|
|
128
|
+
* Whether checkout overlay is currently open
|
|
129
|
+
*/
|
|
130
|
+
isOpen: boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Number of items in cart
|
|
133
|
+
*/
|
|
134
|
+
cartCount: number;
|
|
135
|
+
/**
|
|
136
|
+
* Cart subtotal amount
|
|
137
|
+
*/
|
|
138
|
+
cartTotal: number;
|
|
139
|
+
/**
|
|
140
|
+
* Cart currency code
|
|
141
|
+
*/
|
|
142
|
+
cartCurrency: string;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* React hook for Commerce Engine Checkout
|
|
146
|
+
*
|
|
147
|
+
* @param options - Checkout configuration
|
|
148
|
+
* @returns Checkout state and methods
|
|
149
|
+
*/
|
|
150
|
+
declare function useCheckout(options: UseCheckoutOptions): UseCheckoutReturn;
|
|
151
|
+
//#endregion
|
|
152
|
+
export { type AddToCartItem, type AuthChangeData, type AuthMode, type CartData, type OrderData, type QuickBuyConfig, type SessionMode, type UseCheckoutOptions, type UseCheckoutReturn, useCheckout };
|
|
153
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/use-checkout.ts"],"sourcesContent":[],"mappings":";;;;;;;UAkDiB,kBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAqCJ;;;;;;;;;;;;;aAgBA;;;;;gBAMG;;;;;;;;;;;;;;;;;;;;;;;;uBA6BO;;;;wBAKC;;;;wBAKA;;;;oBAKJ;;;;;UAMH,iBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiED,WAAA,UAAqB,qBAAqB"}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { AddToCartItem, AuthChangeData, AuthChangeData as AuthChangeData$1, AuthMode, AuthMode as AuthMode$1, CartData, CartData as CartData$1, ErrorData, OrderData, OrderData as OrderData$1, QuickBuyConfig, QuickBuyConfig as QuickBuyConfig$1, SessionMode, SessionMode as SessionMode$1 } from "@commercengine/js";
|
|
2
|
+
|
|
3
|
+
//#region src/use-checkout.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Options for useCheckout hook
|
|
7
|
+
*/
|
|
8
|
+
interface UseCheckoutOptions {
|
|
9
|
+
/**
|
|
10
|
+
* Your Commerce Engine Store ID
|
|
11
|
+
* @example "store_abc123"
|
|
12
|
+
*/
|
|
13
|
+
storeId?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Your Commerce Engine API Key
|
|
16
|
+
* @example "ak_test_xyz789"
|
|
17
|
+
*/
|
|
18
|
+
apiKey?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Checkout URL for local development
|
|
21
|
+
* In production, URL is resolved from storeId/apiKey
|
|
22
|
+
*/
|
|
23
|
+
url?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Theme preference
|
|
26
|
+
* @default "system"
|
|
27
|
+
*/
|
|
28
|
+
theme?: "light" | "dark" | "system";
|
|
29
|
+
/**
|
|
30
|
+
* Z-index for the checkout overlay
|
|
31
|
+
* @default 99999
|
|
32
|
+
*/
|
|
33
|
+
zIndex?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Authentication mode
|
|
36
|
+
* - 'managed': Checkout manages token lifecycle (default)
|
|
37
|
+
* - 'provided': Parent manages tokens, checkout uses in-memory only
|
|
38
|
+
* @default "managed"
|
|
39
|
+
*/
|
|
40
|
+
authMode?: AuthMode$1;
|
|
41
|
+
/**
|
|
42
|
+
* Initial access token (if user already logged in)
|
|
43
|
+
*/
|
|
44
|
+
accessToken?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Initial refresh token
|
|
47
|
+
*/
|
|
48
|
+
refreshToken?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Quick buy configuration for "Buy Now" flows
|
|
51
|
+
* When provided, adds the product to cart on initialization
|
|
52
|
+
*/
|
|
53
|
+
quickBuy?: QuickBuyConfig$1;
|
|
54
|
+
/**
|
|
55
|
+
* Session behavior when quick buy is used
|
|
56
|
+
* @default "continue-existing"
|
|
57
|
+
*/
|
|
58
|
+
sessionMode?: SessionMode$1;
|
|
59
|
+
/**
|
|
60
|
+
* Auto-detect quick buy params from parent page URL
|
|
61
|
+
* When enabled, SDK parses window.location.search for:
|
|
62
|
+
* - product_id, variant_id, qty/quantity, session_mode
|
|
63
|
+
* Useful for ad-driven traffic to embedded checkout pages
|
|
64
|
+
* @default false
|
|
65
|
+
*/
|
|
66
|
+
autoDetectQuickBuy?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Called when checkout iframe is ready
|
|
69
|
+
*/
|
|
70
|
+
onReady?: () => void;
|
|
71
|
+
/**
|
|
72
|
+
* Called when checkout is opened
|
|
73
|
+
*/
|
|
74
|
+
onOpen?: () => void;
|
|
75
|
+
/**
|
|
76
|
+
* Called when checkout is closed
|
|
77
|
+
*/
|
|
78
|
+
onClose?: () => void;
|
|
79
|
+
/**
|
|
80
|
+
* Called when order is completed
|
|
81
|
+
*/
|
|
82
|
+
onComplete?: (order: OrderData$1) => void;
|
|
83
|
+
/**
|
|
84
|
+
* Called when cart state changes
|
|
85
|
+
*/
|
|
86
|
+
onCartUpdate?: (cart: CartData$1) => void;
|
|
87
|
+
/**
|
|
88
|
+
* Called when auth state changes
|
|
89
|
+
*/
|
|
90
|
+
onAuthChange?: (auth: AuthChangeData$1) => void;
|
|
91
|
+
/**
|
|
92
|
+
* Called when checkout encounters a configuration error
|
|
93
|
+
*/
|
|
94
|
+
onError?: (error: ErrorData) => void;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Return value from useCheckout hook
|
|
98
|
+
*/
|
|
99
|
+
interface UseCheckoutReturn {
|
|
100
|
+
/**
|
|
101
|
+
* Open the cart drawer
|
|
102
|
+
*/
|
|
103
|
+
openCart: () => void;
|
|
104
|
+
/**
|
|
105
|
+
* Open the checkout drawer directly (for Buy Now flow)
|
|
106
|
+
*/
|
|
107
|
+
openCheckout: () => void;
|
|
108
|
+
/**
|
|
109
|
+
* Close the checkout overlay
|
|
110
|
+
*/
|
|
111
|
+
close: () => void;
|
|
112
|
+
/**
|
|
113
|
+
* Update auth tokens (when user logs in/out on parent site)
|
|
114
|
+
*/
|
|
115
|
+
updateTokens: (accessToken: string, refreshToken?: string) => void;
|
|
116
|
+
/**
|
|
117
|
+
* Add item to cart
|
|
118
|
+
* @param productId - Product ID (required)
|
|
119
|
+
* @param variantId - Variant ID (required, null for non-variant products)
|
|
120
|
+
* @param quantity - Quantity to add (default: 1)
|
|
121
|
+
*/
|
|
122
|
+
addToCart: (productId: string, variantId: string | null, quantity?: number) => void;
|
|
123
|
+
/**
|
|
124
|
+
* Whether checkout is ready to use
|
|
125
|
+
*/
|
|
126
|
+
isReady: boolean;
|
|
127
|
+
/**
|
|
128
|
+
* Whether checkout overlay is currently open
|
|
129
|
+
*/
|
|
130
|
+
isOpen: boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Number of items in cart
|
|
133
|
+
*/
|
|
134
|
+
cartCount: number;
|
|
135
|
+
/**
|
|
136
|
+
* Cart subtotal amount
|
|
137
|
+
*/
|
|
138
|
+
cartTotal: number;
|
|
139
|
+
/**
|
|
140
|
+
* Cart currency code
|
|
141
|
+
*/
|
|
142
|
+
cartCurrency: string;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* React hook for Commerce Engine Checkout
|
|
146
|
+
*
|
|
147
|
+
* @param options - Checkout configuration
|
|
148
|
+
* @returns Checkout state and methods
|
|
149
|
+
*/
|
|
150
|
+
declare function useCheckout(options: UseCheckoutOptions): UseCheckoutReturn;
|
|
151
|
+
//#endregion
|
|
152
|
+
export { type AddToCartItem, type AuthChangeData, type AuthMode, type CartData, type OrderData, type QuickBuyConfig, type SessionMode, type UseCheckoutOptions, type UseCheckoutReturn, useCheckout };
|
|
153
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/use-checkout.ts"],"sourcesContent":[],"mappings":";;;;;;;UAkDiB,kBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAqCJ;;;;;;;;;;;;;aAgBA;;;;;gBAMG;;;;;;;;;;;;;;;;;;;;;;;;uBA6BO;;;;wBAKC;;;;wBAKA;;;;oBAKJ;;;;;UAMH,iBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiED,WAAA,UAAqB,qBAAqB"}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { Checkout } from "@commercengine/js";
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
3
|
+
|
|
4
|
+
//#region src/use-checkout.ts
|
|
5
|
+
/**
|
|
6
|
+
* useCheckout Hook
|
|
7
|
+
*
|
|
8
|
+
* React hook for Commerce Engine Checkout integration.
|
|
9
|
+
* Handles checkout initialization, state management, and cleanup.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* import { useCheckout } from "@commercengine/react";
|
|
14
|
+
*
|
|
15
|
+
* function MyStore() {
|
|
16
|
+
* const { openCart, openCheckout, cartCount, isReady } = useCheckout({
|
|
17
|
+
* storeId: "store_xxx",
|
|
18
|
+
* apiKey: "ak_xxx",
|
|
19
|
+
* theme: "dark",
|
|
20
|
+
* onComplete: (order) => {
|
|
21
|
+
* console.log("Order placed:", order.orderNumber);
|
|
22
|
+
* window.location.href = "/thank-you";
|
|
23
|
+
* },
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* return (
|
|
27
|
+
* <button onClick={openCart} disabled={!isReady}>
|
|
28
|
+
* Cart ({cartCount})
|
|
29
|
+
* </button>
|
|
30
|
+
* );
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
/**
|
|
35
|
+
* React hook for Commerce Engine Checkout
|
|
36
|
+
*
|
|
37
|
+
* @param options - Checkout configuration
|
|
38
|
+
* @returns Checkout state and methods
|
|
39
|
+
*/
|
|
40
|
+
function useCheckout(options) {
|
|
41
|
+
const checkoutRef = useRef(null);
|
|
42
|
+
const [isReady, setIsReady] = useState(false);
|
|
43
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
44
|
+
const [cart, setCart] = useState({
|
|
45
|
+
count: 0,
|
|
46
|
+
total: 0,
|
|
47
|
+
currency: "INR"
|
|
48
|
+
});
|
|
49
|
+
const optionsRef = useRef(options);
|
|
50
|
+
optionsRef.current = options;
|
|
51
|
+
const { url, storeId, apiKey } = options;
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
if (typeof window === "undefined") return;
|
|
54
|
+
const opts = optionsRef.current;
|
|
55
|
+
const checkout = new Checkout({
|
|
56
|
+
url,
|
|
57
|
+
storeId,
|
|
58
|
+
apiKey,
|
|
59
|
+
theme: opts.theme,
|
|
60
|
+
authMode: opts.authMode,
|
|
61
|
+
accessToken: opts.accessToken,
|
|
62
|
+
refreshToken: opts.refreshToken,
|
|
63
|
+
quickBuy: opts.quickBuy,
|
|
64
|
+
sessionMode: opts.sessionMode,
|
|
65
|
+
autoDetectQuickBuy: opts.autoDetectQuickBuy,
|
|
66
|
+
appearance: { zIndex: opts.zIndex },
|
|
67
|
+
onReady: () => {
|
|
68
|
+
setIsReady(true);
|
|
69
|
+
optionsRef.current.onReady?.();
|
|
70
|
+
},
|
|
71
|
+
onOpen: () => {
|
|
72
|
+
setIsOpen(true);
|
|
73
|
+
optionsRef.current.onOpen?.();
|
|
74
|
+
},
|
|
75
|
+
onClose: () => {
|
|
76
|
+
setIsOpen(false);
|
|
77
|
+
optionsRef.current.onClose?.();
|
|
78
|
+
},
|
|
79
|
+
onComplete: (order) => {
|
|
80
|
+
optionsRef.current.onComplete?.(order);
|
|
81
|
+
},
|
|
82
|
+
onCartUpdate: (cartData) => {
|
|
83
|
+
setCart(cartData);
|
|
84
|
+
optionsRef.current.onCartUpdate?.(cartData);
|
|
85
|
+
},
|
|
86
|
+
onAuthChange: (auth) => {
|
|
87
|
+
optionsRef.current.onAuthChange?.(auth);
|
|
88
|
+
},
|
|
89
|
+
onError: (error) => {
|
|
90
|
+
setIsReady(true);
|
|
91
|
+
optionsRef.current.onError?.(error);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
checkoutRef.current = checkout;
|
|
95
|
+
return () => {
|
|
96
|
+
checkout.destroy();
|
|
97
|
+
checkoutRef.current = null;
|
|
98
|
+
setIsReady(false);
|
|
99
|
+
setIsOpen(false);
|
|
100
|
+
};
|
|
101
|
+
}, [
|
|
102
|
+
url,
|
|
103
|
+
storeId,
|
|
104
|
+
apiKey
|
|
105
|
+
]);
|
|
106
|
+
return {
|
|
107
|
+
openCart: useCallback(() => {
|
|
108
|
+
checkoutRef.current?.openCart();
|
|
109
|
+
}, []),
|
|
110
|
+
openCheckout: useCallback(() => {
|
|
111
|
+
checkoutRef.current?.openCheckout();
|
|
112
|
+
}, []),
|
|
113
|
+
close: useCallback(() => {
|
|
114
|
+
checkoutRef.current?.close();
|
|
115
|
+
}, []),
|
|
116
|
+
updateTokens: useCallback((accessToken, refreshToken) => {
|
|
117
|
+
checkoutRef.current?.updateTokens(accessToken, refreshToken);
|
|
118
|
+
}, []),
|
|
119
|
+
addToCart: useCallback((productId, variantId, quantity) => {
|
|
120
|
+
checkoutRef.current?.addToCart(productId, variantId, quantity);
|
|
121
|
+
}, []),
|
|
122
|
+
isReady,
|
|
123
|
+
isOpen,
|
|
124
|
+
cartCount: cart.count,
|
|
125
|
+
cartTotal: cart.total,
|
|
126
|
+
cartCurrency: cart.currency
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
//#endregion
|
|
131
|
+
export { useCheckout };
|
|
132
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/use-checkout.ts"],"sourcesContent":["/**\n * useCheckout Hook\n *\n * React hook for Commerce Engine Checkout integration.\n * Handles checkout initialization, state management, and cleanup.\n *\n * @example\n * ```tsx\n * import { useCheckout } from \"@commercengine/react\";\n *\n * function MyStore() {\n * const { openCart, openCheckout, cartCount, isReady } = useCheckout({\n * storeId: \"store_xxx\",\n * apiKey: \"ak_xxx\",\n * theme: \"dark\",\n * onComplete: (order) => {\n * console.log(\"Order placed:\", order.orderNumber);\n * window.location.href = \"/thank-you\";\n * },\n * });\n *\n * return (\n * <button onClick={openCart} disabled={!isReady}>\n * Cart ({cartCount})\n * </button>\n * );\n * }\n * ```\n */\n\nimport {\n type AuthChangeData,\n type AuthMode,\n type CartData,\n Checkout,\n type CheckoutConfig,\n type ErrorData,\n type OrderData,\n type QuickBuyConfig,\n type SessionMode,\n} from \"@commercengine/js\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/**\n * Options for useCheckout hook\n */\nexport interface UseCheckoutOptions {\n /**\n * Your Commerce Engine Store ID\n * @example \"store_abc123\"\n */\n storeId?: string;\n\n /**\n * Your Commerce Engine API Key\n * @example \"ak_test_xyz789\"\n */\n apiKey?: string;\n\n /**\n * Checkout URL for local development\n * In production, URL is resolved from storeId/apiKey\n */\n url?: string;\n\n /**\n * Theme preference\n * @default \"system\"\n */\n theme?: \"light\" | \"dark\" | \"system\";\n\n /**\n * Z-index for the checkout overlay\n * @default 99999\n */\n zIndex?: number;\n\n /**\n * Authentication mode\n * - 'managed': Checkout manages token lifecycle (default)\n * - 'provided': Parent manages tokens, checkout uses in-memory only\n * @default \"managed\"\n */\n authMode?: AuthMode;\n\n /**\n * Initial access token (if user already logged in)\n */\n accessToken?: string;\n\n /**\n * Initial refresh token\n */\n refreshToken?: string;\n\n /**\n * Quick buy configuration for \"Buy Now\" flows\n * When provided, adds the product to cart on initialization\n */\n quickBuy?: QuickBuyConfig;\n\n /**\n * Session behavior when quick buy is used\n * @default \"continue-existing\"\n */\n sessionMode?: SessionMode;\n\n /**\n * Auto-detect quick buy params from parent page URL\n * When enabled, SDK parses window.location.search for:\n * - product_id, variant_id, qty/quantity, session_mode\n * Useful for ad-driven traffic to embedded checkout pages\n * @default false\n */\n autoDetectQuickBuy?: boolean;\n\n /**\n * Called when checkout iframe is ready\n */\n onReady?: () => void;\n\n /**\n * Called when checkout is opened\n */\n onOpen?: () => void;\n\n /**\n * Called when checkout is closed\n */\n onClose?: () => void;\n\n /**\n * Called when order is completed\n */\n onComplete?: (order: OrderData) => void;\n\n /**\n * Called when cart state changes\n */\n onCartUpdate?: (cart: CartData) => void;\n\n /**\n * Called when auth state changes\n */\n onAuthChange?: (auth: AuthChangeData) => void;\n\n /**\n * Called when checkout encounters a configuration error\n */\n onError?: (error: ErrorData) => void;\n}\n\n/**\n * Return value from useCheckout hook\n */\nexport interface UseCheckoutReturn {\n /**\n * Open the cart drawer\n */\n openCart: () => void;\n\n /**\n * Open the checkout drawer directly (for Buy Now flow)\n */\n openCheckout: () => void;\n\n /**\n * Close the checkout overlay\n */\n close: () => void;\n\n /**\n * Update auth tokens (when user logs in/out on parent site)\n */\n updateTokens: (accessToken: string, refreshToken?: string) => void;\n\n /**\n * Add item to cart\n * @param productId - Product ID (required)\n * @param variantId - Variant ID (required, null for non-variant products)\n * @param quantity - Quantity to add (default: 1)\n */\n addToCart: (productId: string, variantId: string | null, quantity?: number) => void;\n\n /**\n * Whether checkout is ready to use\n */\n isReady: boolean;\n\n /**\n * Whether checkout overlay is currently open\n */\n isOpen: boolean;\n\n /**\n * Number of items in cart\n */\n cartCount: number;\n\n /**\n * Cart subtotal amount\n */\n cartTotal: number;\n\n /**\n * Cart currency code\n */\n cartCurrency: string;\n}\n\n// =============================================================================\n// HOOK\n// =============================================================================\n\n/**\n * React hook for Commerce Engine Checkout\n *\n * @param options - Checkout configuration\n * @returns Checkout state and methods\n */\nexport function useCheckout(options: UseCheckoutOptions): UseCheckoutReturn {\n const checkoutRef = useRef<Checkout | null>(null);\n const [isReady, setIsReady] = useState(false);\n const [isOpen, setIsOpen] = useState(false);\n const [cart, setCart] = useState<CartData>({ count: 0, total: 0, currency: \"INR\" });\n\n // Store options in ref to avoid recreating checkout on callback changes\n // This allows stable callbacks while still using latest callback values\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n // Destructure stable keys for dependency array\n const { url, storeId, apiKey } = options;\n\n // Initialize checkout on mount or when key config changes\n useEffect(() => {\n // Skip on server\n if (typeof window === \"undefined\") return;\n\n // Get current options from ref for non-key values\n const opts = optionsRef.current;\n\n const config: CheckoutConfig = {\n url,\n storeId,\n apiKey,\n theme: opts.theme,\n authMode: opts.authMode,\n accessToken: opts.accessToken,\n refreshToken: opts.refreshToken,\n quickBuy: opts.quickBuy,\n sessionMode: opts.sessionMode,\n autoDetectQuickBuy: opts.autoDetectQuickBuy,\n appearance: {\n zIndex: opts.zIndex,\n },\n onReady: () => {\n setIsReady(true);\n optionsRef.current.onReady?.();\n },\n onOpen: () => {\n setIsOpen(true);\n optionsRef.current.onOpen?.();\n },\n onClose: () => {\n setIsOpen(false);\n optionsRef.current.onClose?.();\n },\n onComplete: (order) => {\n optionsRef.current.onComplete?.(order);\n },\n onCartUpdate: (cartData) => {\n setCart(cartData);\n optionsRef.current.onCartUpdate?.(cartData);\n },\n onAuthChange: (auth) => {\n optionsRef.current.onAuthChange?.(auth);\n },\n onError: (error) => {\n // Still set ready so buttons are enabled (error drawer will show)\n setIsReady(true);\n optionsRef.current.onError?.(error);\n },\n };\n\n const checkout = new Checkout(config);\n checkoutRef.current = checkout;\n\n return () => {\n checkout.destroy();\n checkoutRef.current = null;\n setIsReady(false);\n setIsOpen(false);\n };\n // Only reinitialize when URL or credentials change\n // Other options like theme, tokens, callbacks are read from optionsRef\n }, [url, storeId, apiKey]);\n\n // Stable callback refs\n const openCart = useCallback(() => {\n checkoutRef.current?.openCart();\n }, []);\n\n const openCheckout = useCallback(() => {\n checkoutRef.current?.openCheckout();\n }, []);\n\n const close = useCallback(() => {\n checkoutRef.current?.close();\n }, []);\n\n const updateTokens = useCallback((accessToken: string, refreshToken?: string) => {\n checkoutRef.current?.updateTokens(accessToken, refreshToken);\n }, []);\n\n const addToCart = useCallback(\n (productId: string, variantId: string | null, quantity?: number) => {\n checkoutRef.current?.addToCart(productId, variantId, quantity);\n },\n []\n );\n\n return {\n openCart,\n openCheckout,\n close,\n updateTokens,\n addToCart,\n isReady,\n isOpen,\n cartCount: cart.count,\n cartTotal: cart.total,\n cartCurrency: cart.currency,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgOA,SAAgB,YAAY,SAAgD;CAC1E,MAAM,cAAc,OAAwB,KAAK;CACjD,MAAM,CAAC,SAAS,cAAc,SAAS,MAAM;CAC7C,MAAM,CAAC,QAAQ,aAAa,SAAS,MAAM;CAC3C,MAAM,CAAC,MAAM,WAAW,SAAmB;EAAE,OAAO;EAAG,OAAO;EAAG,UAAU;EAAO,CAAC;CAInF,MAAM,aAAa,OAAO,QAAQ;AAClC,YAAW,UAAU;CAGrB,MAAM,EAAE,KAAK,SAAS,WAAW;AAGjC,iBAAgB;AAEd,MAAI,OAAO,WAAW,YAAa;EAGnC,MAAM,OAAO,WAAW;EA6CxB,MAAM,WAAW,IAAI,SA3CU;GAC7B;GACA;GACA;GACA,OAAO,KAAK;GACZ,UAAU,KAAK;GACf,aAAa,KAAK;GAClB,cAAc,KAAK;GACnB,UAAU,KAAK;GACf,aAAa,KAAK;GAClB,oBAAoB,KAAK;GACzB,YAAY,EACV,QAAQ,KAAK,QACd;GACD,eAAe;AACb,eAAW,KAAK;AAChB,eAAW,QAAQ,WAAW;;GAEhC,cAAc;AACZ,cAAU,KAAK;AACf,eAAW,QAAQ,UAAU;;GAE/B,eAAe;AACb,cAAU,MAAM;AAChB,eAAW,QAAQ,WAAW;;GAEhC,aAAa,UAAU;AACrB,eAAW,QAAQ,aAAa,MAAM;;GAExC,eAAe,aAAa;AAC1B,YAAQ,SAAS;AACjB,eAAW,QAAQ,eAAe,SAAS;;GAE7C,eAAe,SAAS;AACtB,eAAW,QAAQ,eAAe,KAAK;;GAEzC,UAAU,UAAU;AAElB,eAAW,KAAK;AAChB,eAAW,QAAQ,UAAU,MAAM;;GAEtC,CAEoC;AACrC,cAAY,UAAU;AAEtB,eAAa;AACX,YAAS,SAAS;AAClB,eAAY,UAAU;AACtB,cAAW,MAAM;AACjB,aAAU,MAAM;;IAIjB;EAAC;EAAK;EAAS;EAAO,CAAC;AA0B1B,QAAO;EACL,UAxBe,kBAAkB;AACjC,eAAY,SAAS,UAAU;KAC9B,EAAE,CAAC;EAuBJ,cArBmB,kBAAkB;AACrC,eAAY,SAAS,cAAc;KAClC,EAAE,CAAC;EAoBJ,OAlBY,kBAAkB;AAC9B,eAAY,SAAS,OAAO;KAC3B,EAAE,CAAC;EAiBJ,cAfmB,aAAa,aAAqB,iBAA0B;AAC/E,eAAY,SAAS,aAAa,aAAa,aAAa;KAC3D,EAAE,CAAC;EAcJ,WAZgB,aACf,WAAmB,WAA0B,aAAsB;AAClE,eAAY,SAAS,UAAU,WAAW,WAAW,SAAS;KAEhE,EAAE,CACH;EAQC;EACA;EACA,WAAW,KAAK;EAChB,WAAW,KAAK;EAChB,cAAc,KAAK;EACpB"}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@commercengine/react",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Commerce Engine Checkout - React SDK",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.cjs",
|
|
7
|
+
"module": "dist/index.mjs",
|
|
8
|
+
"types": "dist/index.d.mts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.mts",
|
|
13
|
+
"default": "./dist/index.mjs"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"./package.json": "./package.json"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@commercengine/js": "0.1.0"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"react": ">=17.0.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/react": "^18.3.18",
|
|
33
|
+
"react": "^18.3.1",
|
|
34
|
+
"tsdown": "^0.18.4",
|
|
35
|
+
"typescript": "^5.9.3"
|
|
36
|
+
},
|
|
37
|
+
"keywords": [
|
|
38
|
+
"commercengine",
|
|
39
|
+
"checkout",
|
|
40
|
+
"react",
|
|
41
|
+
"hook",
|
|
42
|
+
"ecommerce"
|
|
43
|
+
],
|
|
44
|
+
"license": "MIT",
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"homepage": "https://docs.commercengine.io",
|
|
49
|
+
"scripts": {
|
|
50
|
+
"dev": "tsdown --watch",
|
|
51
|
+
"build": "tsdown"
|
|
52
|
+
}
|
|
53
|
+
}
|