@usethrottle/checkout-react 1.0.1 → 1.2.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/dist/index.d.cts CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { CSSProperties, RefObject } from 'react';
3
+ import { Cart, AddLineItemInput, UpdateLineItemInput, SelectShippingInput, CheckoutHandoffInput, CheckoutHandoff, SelectedShipping } from '@usethrottle/cart';
3
4
 
4
5
  /**
5
6
  * Envelope every Throttle iframe message carries. Lets parents
@@ -177,4 +178,156 @@ interface UseThrottleEventsOptions {
177
178
  */
178
179
  declare function useThrottleEvents({ iframeRef, expectedOrigin, onMessage }: UseThrottleEventsOptions): void;
179
180
 
180
- export { CheckoutEmbed, type CheckoutEmbedExtraProps, PaymentEmbed, type RecurringIntent, CheckoutEmbed as ThrottleCheckout, type ThrottleEmbedProps, type ThrottleEnvelope, type ThrottleEvent, type ThrottleMessage, type ThrottleParentCommand, type ThrottleParentEnvelope, type ThrottleParentMessage, useThrottleEvents };
181
+ interface UseCartSessionOptions {
182
+ /** Application UUID. */
183
+ applicationId: string;
184
+ /** Workspace environment UUID the publishable token was minted for. */
185
+ environmentId: string;
186
+ /** Publishable storefront quote token (`pk_…`). */
187
+ quoteToken: string;
188
+ baseUrl?: string;
189
+ /**
190
+ * localStorage key for persisting the session id across page loads. Default
191
+ * `'throttle.cartSessionId'`. Pass `null` to disable persistence (in-memory
192
+ * only).
193
+ */
194
+ storageKey?: string | null;
195
+ }
196
+ interface UseCartSessionResult {
197
+ /** Current cart snapshot, or null before the first item / resume. */
198
+ cart: Cart | null;
199
+ /** Current opaque session id, or null before the first item. */
200
+ cartSessionId: string | null;
201
+ /** True while a request is in flight. */
202
+ loading: boolean;
203
+ /** Last error, or null. */
204
+ error: Error | null;
205
+ addItem: (input: AddLineItemInput) => Promise<void>;
206
+ updateItem: (itemId: string, input: UpdateLineItemInput) => Promise<void>;
207
+ removeItem: (itemId: string) => Promise<void>;
208
+ selectShipping: (input: SelectShippingInput) => Promise<void>;
209
+ clearShipping: () => Promise<void>;
210
+ applyDiscount: (code: string) => Promise<void>;
211
+ removeDiscount: () => Promise<void>;
212
+ /** Hand off to checkout. Returns the hand-off (redirect the buyer to `checkoutUrl`). */
213
+ checkout: (input: CheckoutHandoffInput) => Promise<CheckoutHandoff>;
214
+ /** Re-fetch the current cart. */
215
+ refresh: () => Promise<void>;
216
+ /** Forget the current session (a new cart is created on the next item). */
217
+ reset: () => void;
218
+ }
219
+ /**
220
+ * React hook for backend-less cart ownership. Wraps {@link CartSessionClient}:
221
+ * creates the Throttle cart lazily on the first `addItem` (so empty carts
222
+ * aren't created on every page load), persists the session id to localStorage,
223
+ * and resumes it on the next visit. Mutations update reactive `cart` state.
224
+ *
225
+ * ```tsx
226
+ * const cart = useCartSession({ applicationId, environmentId, quoteToken });
227
+ * <button onClick={() => cart.addItem({ name: 'Widget', unitPrice: 2999, quantity: 1 })}>Add</button>
228
+ * <button onClick={async () => {
229
+ * const { checkoutUrl } = await cart.checkout({ returnUrl, cancelUrl });
230
+ * window.location.href = checkoutUrl;
231
+ * }}>Checkout</button>
232
+ * ```
233
+ */
234
+ declare function useCartSession(options: UseCartSessionOptions): UseCartSessionResult;
235
+
236
+ /**
237
+ * Lifecycle status for the checkout orchestration.
238
+ * - `idle` — no work in flight, no cart yet
239
+ * - `loading` — a request is in flight
240
+ * - `recovering` — the cart went stale (converted/abandoned); rebuilding from the
241
+ * last-known line items into a fresh session
242
+ * - `ready` — a cart is present and no request is in flight
243
+ * - `error` — the last operation failed (see `error`)
244
+ */
245
+ type ThrottleCheckoutStatus = 'idle' | 'loading' | 'recovering' | 'ready' | 'error';
246
+ interface CheckoutTotals {
247
+ currency: string;
248
+ subtotal: number;
249
+ discountTotal: number;
250
+ shippingTotal: number;
251
+ taxTotal: number;
252
+ total: number;
253
+ }
254
+ interface UseThrottleCheckoutOptions {
255
+ /** Application UUID. */
256
+ applicationId: string;
257
+ /** Workspace environment UUID the publishable token was minted for. */
258
+ environmentId: string;
259
+ /** Publishable storefront quote token (`pk_…`). */
260
+ quoteToken: string;
261
+ baseUrl?: string;
262
+ /**
263
+ * localStorage key for persisting the cart session id across page loads.
264
+ * Default `'throttle.cartSessionId'`. Pass `null` to disable persistence.
265
+ */
266
+ storageKey?: string | null;
267
+ /**
268
+ * Auto-recover from a stale cart. When a mutation fails with
269
+ * {@link CartNotOpenError} (the cart was converted by a completed order, or
270
+ * abandoned), the hook starts a fresh session, re-adds the last-known line
271
+ * items and re-selects the shipping method, then retries the operation once.
272
+ * Default `true`. Set `false` to surface {@link CartNotOpenError} instead.
273
+ */
274
+ autoRecover?: boolean;
275
+ }
276
+ interface UseThrottleCheckoutResult {
277
+ /** Current cart snapshot, or null before the first item / resume. */
278
+ cart: Cart | null;
279
+ /** Current cart session id, or null before the first item. */
280
+ cartSessionId: string | null;
281
+ /** Coarse lifecycle status — drive your UI off this rather than `cart === null`. */
282
+ status: ThrottleCheckoutStatus;
283
+ /** Last error, or null. */
284
+ error: Error | null;
285
+ /** The selected shipping method, bound to the cart (never a shadow copy). */
286
+ selectedMethod: SelectedShipping | null;
287
+ /** Live totals, bound to the cart. Null before a cart exists. */
288
+ totals: CheckoutTotals | null;
289
+ addItem: (input: AddLineItemInput) => Promise<void>;
290
+ updateItem: (itemId: string, input: UpdateLineItemInput) => Promise<void>;
291
+ removeItem: (itemId: string) => Promise<void>;
292
+ /** Lock a shipping method. One call — the returned cart carries recomputed totals. */
293
+ selectMethod: (input: SelectShippingInput) => Promise<void>;
294
+ clearShipping: () => Promise<void>;
295
+ applyDiscount: (code: string) => Promise<void>;
296
+ removeDiscount: () => Promise<void>;
297
+ /**
298
+ * Hand off to checkout. Returns the hand-off — use `checkoutSessionId` with
299
+ * `<PaymentEmbed sessionId={…}>` (or redirect the buyer to `checkoutUrl`).
300
+ */
301
+ createSession: (input: CheckoutHandoffInput) => Promise<CheckoutHandoff>;
302
+ /** Re-fetch the current cart. */
303
+ refresh: () => Promise<void>;
304
+ /** Forget the current session (a new cart is created on the next item). */
305
+ reset: () => void;
306
+ }
307
+ /**
308
+ * Orchestrates a backend-less storefront checkout on top of
309
+ * {@link CartSessionClient}, bundling the pieces every storefront otherwise
310
+ * re-implements:
311
+ *
312
+ * - **Cart as source of truth** — `selectedMethod` and `totals` are read straight
313
+ * off the cart; there is no shadow copy to drift.
314
+ * - **One-call shipping select** — `selectMethod` locks the method and returns the
315
+ * cart with recomputed totals in a single round trip.
316
+ * - **Stale-cart recovery** — a {@link CartNotOpenError} (cart converted by a
317
+ * completed order, or abandoned) transparently rebuilds a fresh session from
318
+ * the last-known line items + shipping and retries (`status === 'recovering'`).
319
+ * - **Session handoff** — `createSession` returns the `checkoutSessionId` for
320
+ * `<PaymentEmbed>`.
321
+ *
322
+ * Address collection is handled inside the checkout embed (the hosted/full
323
+ * checkout collects shipping/billing), so this hook intentionally does not write
324
+ * addresses to the cart.
325
+ *
326
+ * ```tsx
327
+ * const { addItem, selectMethod, totals, createSession, status } =
328
+ * useThrottleCheckout({ applicationId, environmentId, quoteToken });
329
+ * ```
330
+ */
331
+ declare function useThrottleCheckout(options: UseThrottleCheckoutOptions): UseThrottleCheckoutResult;
332
+
333
+ export { CheckoutEmbed, type CheckoutEmbedExtraProps, type CheckoutTotals, PaymentEmbed, type RecurringIntent, CheckoutEmbed as ThrottleCheckout, type ThrottleCheckoutStatus, type ThrottleEmbedProps, type ThrottleEnvelope, type ThrottleEvent, type ThrottleMessage, type ThrottleParentCommand, type ThrottleParentEnvelope, type ThrottleParentMessage, type UseCartSessionOptions, type UseCartSessionResult, type UseThrottleCheckoutOptions, type UseThrottleCheckoutResult, useCartSession, useThrottleCheckout, useThrottleEvents };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { CSSProperties, RefObject } from 'react';
3
+ import { Cart, AddLineItemInput, UpdateLineItemInput, SelectShippingInput, CheckoutHandoffInput, CheckoutHandoff, SelectedShipping } from '@usethrottle/cart';
3
4
 
4
5
  /**
5
6
  * Envelope every Throttle iframe message carries. Lets parents
@@ -177,4 +178,156 @@ interface UseThrottleEventsOptions {
177
178
  */
178
179
  declare function useThrottleEvents({ iframeRef, expectedOrigin, onMessage }: UseThrottleEventsOptions): void;
179
180
 
180
- export { CheckoutEmbed, type CheckoutEmbedExtraProps, PaymentEmbed, type RecurringIntent, CheckoutEmbed as ThrottleCheckout, type ThrottleEmbedProps, type ThrottleEnvelope, type ThrottleEvent, type ThrottleMessage, type ThrottleParentCommand, type ThrottleParentEnvelope, type ThrottleParentMessage, useThrottleEvents };
181
+ interface UseCartSessionOptions {
182
+ /** Application UUID. */
183
+ applicationId: string;
184
+ /** Workspace environment UUID the publishable token was minted for. */
185
+ environmentId: string;
186
+ /** Publishable storefront quote token (`pk_…`). */
187
+ quoteToken: string;
188
+ baseUrl?: string;
189
+ /**
190
+ * localStorage key for persisting the session id across page loads. Default
191
+ * `'throttle.cartSessionId'`. Pass `null` to disable persistence (in-memory
192
+ * only).
193
+ */
194
+ storageKey?: string | null;
195
+ }
196
+ interface UseCartSessionResult {
197
+ /** Current cart snapshot, or null before the first item / resume. */
198
+ cart: Cart | null;
199
+ /** Current opaque session id, or null before the first item. */
200
+ cartSessionId: string | null;
201
+ /** True while a request is in flight. */
202
+ loading: boolean;
203
+ /** Last error, or null. */
204
+ error: Error | null;
205
+ addItem: (input: AddLineItemInput) => Promise<void>;
206
+ updateItem: (itemId: string, input: UpdateLineItemInput) => Promise<void>;
207
+ removeItem: (itemId: string) => Promise<void>;
208
+ selectShipping: (input: SelectShippingInput) => Promise<void>;
209
+ clearShipping: () => Promise<void>;
210
+ applyDiscount: (code: string) => Promise<void>;
211
+ removeDiscount: () => Promise<void>;
212
+ /** Hand off to checkout. Returns the hand-off (redirect the buyer to `checkoutUrl`). */
213
+ checkout: (input: CheckoutHandoffInput) => Promise<CheckoutHandoff>;
214
+ /** Re-fetch the current cart. */
215
+ refresh: () => Promise<void>;
216
+ /** Forget the current session (a new cart is created on the next item). */
217
+ reset: () => void;
218
+ }
219
+ /**
220
+ * React hook for backend-less cart ownership. Wraps {@link CartSessionClient}:
221
+ * creates the Throttle cart lazily on the first `addItem` (so empty carts
222
+ * aren't created on every page load), persists the session id to localStorage,
223
+ * and resumes it on the next visit. Mutations update reactive `cart` state.
224
+ *
225
+ * ```tsx
226
+ * const cart = useCartSession({ applicationId, environmentId, quoteToken });
227
+ * <button onClick={() => cart.addItem({ name: 'Widget', unitPrice: 2999, quantity: 1 })}>Add</button>
228
+ * <button onClick={async () => {
229
+ * const { checkoutUrl } = await cart.checkout({ returnUrl, cancelUrl });
230
+ * window.location.href = checkoutUrl;
231
+ * }}>Checkout</button>
232
+ * ```
233
+ */
234
+ declare function useCartSession(options: UseCartSessionOptions): UseCartSessionResult;
235
+
236
+ /**
237
+ * Lifecycle status for the checkout orchestration.
238
+ * - `idle` — no work in flight, no cart yet
239
+ * - `loading` — a request is in flight
240
+ * - `recovering` — the cart went stale (converted/abandoned); rebuilding from the
241
+ * last-known line items into a fresh session
242
+ * - `ready` — a cart is present and no request is in flight
243
+ * - `error` — the last operation failed (see `error`)
244
+ */
245
+ type ThrottleCheckoutStatus = 'idle' | 'loading' | 'recovering' | 'ready' | 'error';
246
+ interface CheckoutTotals {
247
+ currency: string;
248
+ subtotal: number;
249
+ discountTotal: number;
250
+ shippingTotal: number;
251
+ taxTotal: number;
252
+ total: number;
253
+ }
254
+ interface UseThrottleCheckoutOptions {
255
+ /** Application UUID. */
256
+ applicationId: string;
257
+ /** Workspace environment UUID the publishable token was minted for. */
258
+ environmentId: string;
259
+ /** Publishable storefront quote token (`pk_…`). */
260
+ quoteToken: string;
261
+ baseUrl?: string;
262
+ /**
263
+ * localStorage key for persisting the cart session id across page loads.
264
+ * Default `'throttle.cartSessionId'`. Pass `null` to disable persistence.
265
+ */
266
+ storageKey?: string | null;
267
+ /**
268
+ * Auto-recover from a stale cart. When a mutation fails with
269
+ * {@link CartNotOpenError} (the cart was converted by a completed order, or
270
+ * abandoned), the hook starts a fresh session, re-adds the last-known line
271
+ * items and re-selects the shipping method, then retries the operation once.
272
+ * Default `true`. Set `false` to surface {@link CartNotOpenError} instead.
273
+ */
274
+ autoRecover?: boolean;
275
+ }
276
+ interface UseThrottleCheckoutResult {
277
+ /** Current cart snapshot, or null before the first item / resume. */
278
+ cart: Cart | null;
279
+ /** Current cart session id, or null before the first item. */
280
+ cartSessionId: string | null;
281
+ /** Coarse lifecycle status — drive your UI off this rather than `cart === null`. */
282
+ status: ThrottleCheckoutStatus;
283
+ /** Last error, or null. */
284
+ error: Error | null;
285
+ /** The selected shipping method, bound to the cart (never a shadow copy). */
286
+ selectedMethod: SelectedShipping | null;
287
+ /** Live totals, bound to the cart. Null before a cart exists. */
288
+ totals: CheckoutTotals | null;
289
+ addItem: (input: AddLineItemInput) => Promise<void>;
290
+ updateItem: (itemId: string, input: UpdateLineItemInput) => Promise<void>;
291
+ removeItem: (itemId: string) => Promise<void>;
292
+ /** Lock a shipping method. One call — the returned cart carries recomputed totals. */
293
+ selectMethod: (input: SelectShippingInput) => Promise<void>;
294
+ clearShipping: () => Promise<void>;
295
+ applyDiscount: (code: string) => Promise<void>;
296
+ removeDiscount: () => Promise<void>;
297
+ /**
298
+ * Hand off to checkout. Returns the hand-off — use `checkoutSessionId` with
299
+ * `<PaymentEmbed sessionId={…}>` (or redirect the buyer to `checkoutUrl`).
300
+ */
301
+ createSession: (input: CheckoutHandoffInput) => Promise<CheckoutHandoff>;
302
+ /** Re-fetch the current cart. */
303
+ refresh: () => Promise<void>;
304
+ /** Forget the current session (a new cart is created on the next item). */
305
+ reset: () => void;
306
+ }
307
+ /**
308
+ * Orchestrates a backend-less storefront checkout on top of
309
+ * {@link CartSessionClient}, bundling the pieces every storefront otherwise
310
+ * re-implements:
311
+ *
312
+ * - **Cart as source of truth** — `selectedMethod` and `totals` are read straight
313
+ * off the cart; there is no shadow copy to drift.
314
+ * - **One-call shipping select** — `selectMethod` locks the method and returns the
315
+ * cart with recomputed totals in a single round trip.
316
+ * - **Stale-cart recovery** — a {@link CartNotOpenError} (cart converted by a
317
+ * completed order, or abandoned) transparently rebuilds a fresh session from
318
+ * the last-known line items + shipping and retries (`status === 'recovering'`).
319
+ * - **Session handoff** — `createSession` returns the `checkoutSessionId` for
320
+ * `<PaymentEmbed>`.
321
+ *
322
+ * Address collection is handled inside the checkout embed (the hosted/full
323
+ * checkout collects shipping/billing), so this hook intentionally does not write
324
+ * addresses to the cart.
325
+ *
326
+ * ```tsx
327
+ * const { addItem, selectMethod, totals, createSession, status } =
328
+ * useThrottleCheckout({ applicationId, environmentId, quoteToken });
329
+ * ```
330
+ */
331
+ declare function useThrottleCheckout(options: UseThrottleCheckoutOptions): UseThrottleCheckoutResult;
332
+
333
+ export { CheckoutEmbed, type CheckoutEmbedExtraProps, type CheckoutTotals, PaymentEmbed, type RecurringIntent, CheckoutEmbed as ThrottleCheckout, type ThrottleCheckoutStatus, type ThrottleEmbedProps, type ThrottleEnvelope, type ThrottleEvent, type ThrottleMessage, type ThrottleParentCommand, type ThrottleParentEnvelope, type ThrottleParentMessage, type UseCartSessionOptions, type UseCartSessionResult, type UseThrottleCheckoutOptions, type UseThrottleCheckoutResult, useCartSession, useThrottleCheckout, useThrottleEvents };