@cimplify/sdk 0.8.7 → 0.8.9

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/react.js CHANGED
@@ -1,55 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var React2 = require('react');
3
+ var React3 = require('react');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
 
6
6
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
7
 
8
- var React2__default = /*#__PURE__*/_interopDefault(React2);
8
+ var React3__default = /*#__PURE__*/_interopDefault(React3);
9
9
 
10
- // src/react/index.tsx
11
-
12
- // src/types/elements.ts
13
- var ELEMENT_TYPES = {
14
- AUTH: "auth",
15
- ADDRESS: "address",
16
- PAYMENT: "payment",
17
- CHECKOUT: "checkout"
18
- };
19
- var MESSAGE_TYPES = {
20
- // Parent → Iframe
21
- INIT: "init",
22
- SET_TOKEN: "set_token",
23
- SET_CART: "set_cart",
24
- GET_DATA: "get_data",
25
- PROCESS_CHECKOUT: "process_checkout",
26
- ABORT_CHECKOUT: "abort_checkout",
27
- // Iframe → Parent
28
- READY: "ready",
29
- HEIGHT_CHANGE: "height_change",
30
- AUTHENTICATED: "authenticated",
31
- REQUIRES_OTP: "requires_otp",
32
- ERROR: "error",
33
- ADDRESS_CHANGED: "address_changed",
34
- ADDRESS_SELECTED: "address_selected",
35
- PAYMENT_METHOD_SELECTED: "payment_method_selected",
36
- TOKEN_REFRESHED: "token_refreshed",
37
- LOGOUT_COMPLETE: "logout_complete",
38
- CONTACT_PROVIDED: "contact_provided",
39
- CHECKOUT_STATUS: "checkout_status",
40
- CHECKOUT_COMPLETE: "checkout_complete",
41
- ORDER_TYPE_CHANGED: "order_type_changed",
42
- REQUEST_SUBMIT: "request_submit"
43
- };
44
- var EVENT_TYPES = {
45
- READY: "ready",
46
- AUTHENTICATED: "authenticated",
47
- REQUIRES_OTP: "requires_otp",
48
- ERROR: "error",
49
- CHANGE: "change",
50
- ORDER_TYPE_CHANGED: "order_type_changed",
51
- REQUEST_SUBMIT: "request_submit"
52
- };
10
+ // src/ads/index.tsx
53
11
 
54
12
  // src/ads/identity.ts
55
13
  var COOKIE_NAME = "_cimplify_uid";
@@ -201,7 +159,7 @@ function deriveAdsApiUrl() {
201
159
  }
202
160
  return "https://api.cimplify.io";
203
161
  }
204
- var AdContext = React2.createContext({
162
+ var AdContext = React3.createContext({
205
163
  siteId: null,
206
164
  config: null,
207
165
  isLoading: true,
@@ -209,7 +167,7 @@ var AdContext = React2.createContext({
209
167
  apiBase: "https://api.cimplify.io"
210
168
  });
211
169
  function useAds() {
212
- return React2.useContext(AdContext);
170
+ return React3.useContext(AdContext);
213
171
  }
214
172
  function AdProvider({
215
173
  siteId,
@@ -218,10 +176,10 @@ function AdProvider({
218
176
  children
219
177
  }) {
220
178
  const resolvedApiBase = apiBase || deriveAdsApiUrl();
221
- const [config, setConfig] = React2.useState(null);
222
- const [isLoading, setIsLoading] = React2.useState(true);
223
- const [identity, setIdentity] = React2.useState(null);
224
- React2.useEffect(() => {
179
+ const [config, setConfig] = React3.useState(null);
180
+ const [isLoading, setIsLoading] = React3.useState(true);
181
+ const [identity, setIdentity] = React3.useState(null);
182
+ React3.useEffect(() => {
225
183
  const userIdentity = getUserIdentity(authenticatedAccountId);
226
184
  setIdentity(userIdentity);
227
185
  fetch(`${resolvedApiBase}/ads/config/${siteId}`).then((r) => r.json()).then((data) => {
@@ -244,11 +202,11 @@ function Ad({
244
202
  onClick
245
203
  }) {
246
204
  const { siteId, config, isLoading, identity, apiBase } = useAds();
247
- const [ad, setAd] = React2.useState(null);
248
- const [error, setError] = React2.useState(false);
249
- const impressionTracked = React2.useRef(false);
250
- const containerRef = React2.useRef(null);
251
- React2.useEffect(() => {
205
+ const [ad, setAd] = React3.useState(null);
206
+ const [error, setError] = React3.useState(false);
207
+ const impressionTracked = React3.useRef(false);
208
+ const containerRef = React3.useRef(null);
209
+ React3.useEffect(() => {
252
210
  if (isLoading || !config?.enabled || !siteId || !identity) return;
253
211
  const path = typeof window !== "undefined" ? window.location.pathname : "/";
254
212
  const referrer = typeof document !== "undefined" ? document.referrer : "";
@@ -291,7 +249,7 @@ function Ad({
291
249
  }
292
250
  }).catch(() => setError(true));
293
251
  }, [siteId, config, isLoading, slot, identity, apiBase]);
294
- React2.useEffect(() => {
252
+ React3.useEffect(() => {
295
253
  if (!ad || impressionTracked.current || typeof window === "undefined" || !identity) return;
296
254
  const observer = new IntersectionObserver(
297
255
  ([entry]) => {
@@ -368,12 +326,13 @@ function getSelections(item) {
368
326
  }
369
327
  return void 0;
370
328
  }
371
- function mapItem(item) {
329
+ function mapItem(item, fx) {
330
+ const amt = (value) => fx ? String(fx.convertPrice(value)) : String(value);
372
331
  const result = {
373
332
  name: item.name,
374
333
  quantity: item.quantity,
375
- unit_price: String(item.base_price),
376
- total_price: String(item.total_price),
334
+ unit_price: amt(item.base_price),
335
+ total_price: amt(item.total_price),
377
336
  line_type: item.line_type
378
337
  };
379
338
  if (item.image_url) result.image_url = item.image_url;
@@ -386,7 +345,7 @@ function mapItem(item) {
386
345
  if (item.add_on_options?.length) {
387
346
  result.add_ons = item.add_on_options.map((opt) => ({
388
347
  name: opt.name,
389
- price: String(opt.price ?? "0")
348
+ price: amt(opt.price ?? "0")
390
349
  }));
391
350
  }
392
351
  if (item.special_instructions) {
@@ -394,623 +353,231 @@ function mapItem(item) {
394
353
  }
395
354
  return result;
396
355
  }
397
- function transformToCheckoutCart(cart) {
356
+ function transformToCheckoutCart(cart, fx) {
357
+ const amt = (value) => fx ? String(fx.convertPrice(value)) : String(value);
398
358
  return {
399
- items: cart.items.map(mapItem),
400
- subtotal: String(cart.pricing.subtotal),
401
- tax_amount: String(cart.pricing.tax_amount),
402
- total_discounts: String(cart.pricing.total_discounts),
403
- service_charge: String(cart.pricing.service_charge),
404
- total: String(cart.pricing.total_price),
405
- currency: cart.pricing.currency
359
+ items: cart.items.map((item) => mapItem(item, fx)),
360
+ subtotal: amt(cart.pricing.subtotal),
361
+ tax_amount: amt(cart.pricing.tax_amount),
362
+ total_discounts: amt(cart.pricing.total_discounts),
363
+ service_charge: amt(cart.pricing.service_charge),
364
+ total: amt(cart.pricing.total_price),
365
+ currency: fx?.displayCurrency ?? cart.pricing.currency
406
366
  };
407
367
  }
408
- var SPACE = { sm: 8};
409
- function shellColors(isDark, primaryColor) {
410
- return {
411
- text: isDark ? "#f4f4f5" : "#1a1a1a",
412
- textSecondary: isDark ? "#a1a1aa" : "#52525b",
413
- textMuted: isDark ? "#71717a" : "#a1a1aa",
414
- border: isDark ? "#27272a" : "#e4e4e7",
415
- surface: isDark ? "#18181b" : "#fafafa",
416
- error: "#dc2626",
417
- primary: primaryColor
418
- };
368
+
369
+ // src/types/common.ts
370
+ function money(value) {
371
+ return value;
419
372
  }
420
- function statusToLabel(status) {
421
- if (!status) {
422
- return "";
373
+ function moneyFromNumber(value) {
374
+ return value.toFixed(2);
375
+ }
376
+ var SUPPORTED_CURRENCY_CODES = /* @__PURE__ */ new Set([
377
+ "USD",
378
+ "EUR",
379
+ "GBP",
380
+ "JPY",
381
+ "CNY",
382
+ "CHF",
383
+ "CAD",
384
+ "AUD",
385
+ "GHS",
386
+ "NGN",
387
+ "KES",
388
+ "ZAR",
389
+ "XOF",
390
+ "XAF",
391
+ "EGP",
392
+ "TZS",
393
+ "UGX",
394
+ "RWF",
395
+ "ETB",
396
+ "ZMW",
397
+ "BWP",
398
+ "MUR",
399
+ "NAD",
400
+ "MWK",
401
+ "AOA",
402
+ "CDF",
403
+ "GMD",
404
+ "GNF",
405
+ "LRD",
406
+ "SLL",
407
+ "MZN",
408
+ "BIF",
409
+ "INR",
410
+ "BRL",
411
+ "MXN",
412
+ "KRW",
413
+ "TRY",
414
+ "THB",
415
+ "MYR",
416
+ "PHP",
417
+ "IDR",
418
+ "VND",
419
+ "SGD",
420
+ "HKD",
421
+ "TWD",
422
+ "AED",
423
+ "SAR",
424
+ "ILS"
425
+ ]);
426
+ function isSupportedCurrency(code) {
427
+ return SUPPORTED_CURRENCY_CODES.has(code);
428
+ }
429
+ function currencyCode(value) {
430
+ return value;
431
+ }
432
+ var ErrorCode = {
433
+ // General
434
+ UNKNOWN_ERROR: "UNKNOWN_ERROR",
435
+ NETWORK_ERROR: "NETWORK_ERROR",
436
+ TIMEOUT: "TIMEOUT",
437
+ UNAUTHORIZED: "UNAUTHORIZED",
438
+ NOT_FOUND: "NOT_FOUND"};
439
+ var DOCS_ERROR_BASE_URL = "https://docs.cimplify.io/reference/error-codes";
440
+ function docsUrlForCode(code) {
441
+ return `${DOCS_ERROR_BASE_URL}#${code.toLowerCase().replace(/_/g, "-")}`;
442
+ }
443
+ var ERROR_SUGGESTIONS = {
444
+ UNKNOWN_ERROR: "An unexpected error occurred. Capture the request/response payload and retry with exponential backoff.",
445
+ NETWORK_ERROR: "Check the shopper's connection and retry. If this persists, inspect CORS, DNS, and API reachability.",
446
+ TIMEOUT: "The request exceeded the timeout. Retry once, then poll order status before charging again.",
447
+ UNAUTHORIZED: "Authentication is missing or expired. Ensure a valid access token is set and refresh the session if needed.",
448
+ FORBIDDEN: "The key/session lacks permission for this resource. Verify business ownership and API key scope.",
449
+ NOT_FOUND: "The requested resource does not exist or is not visible in this environment.",
450
+ VALIDATION_ERROR: "One or more fields are invalid. Validate required fields and enum values before retrying.",
451
+ CART_EMPTY: "The cart has no items. Redirect back to menu/catalogue and require at least one line item.",
452
+ CART_EXPIRED: "This cart is no longer active. Recreate a new cart and re-add shopper selections.",
453
+ CART_NOT_FOUND: "Cart could not be located. It may have expired or belongs to a different key/location.",
454
+ ITEM_UNAVAILABLE: "The selected item is unavailable at this location/time. Prompt the shopper to pick an alternative.",
455
+ VARIANT_NOT_FOUND: "The requested variant no longer exists. Refresh product data and require re-selection.",
456
+ VARIANT_OUT_OF_STOCK: "The selected variant is out of stock. Show in-stock variants and block checkout for this line.",
457
+ ADDON_REQUIRED: "A required add-on is missing. Ensure required modifier groups are completed before add-to-cart.",
458
+ ADDON_MAX_EXCEEDED: "Too many add-ons were selected. Enforce max selections client-side before submission.",
459
+ CHECKOUT_VALIDATION_FAILED: "Checkout payload failed validation. Verify customer, order type, and address fields are complete.",
460
+ DELIVERY_ADDRESS_REQUIRED: "Delivery orders require an address. Collect and pass address info before processing checkout.",
461
+ CUSTOMER_INFO_REQUIRED: "Customer details are required. Ensure name/email/phone are available before checkout.",
462
+ QUOTE_NOT_FOUND: "Quote could not be found. Refresh pricing and create a new quote before checkout.",
463
+ QUOTE_EXPIRED: "Quote has expired. Re-fetch pricing to generate a new quote with a valid expiry window.",
464
+ QUOTE_CONSUMED: "Quote has already been used. Request a fresh quote to prevent duplicate checkout attempts.",
465
+ QUOTE_STORAGE_UNAVAILABLE: "Quote storage is temporarily unavailable. Retry shortly and avoid charging until quote fetch succeeds.",
466
+ PAYMENT_FAILED: "Payment provider rejected or failed processing. Show retry/change-method options to the shopper.",
467
+ PAYMENT_CANCELLED: "Payment was cancelled by the shopper or provider flow. Allow a safe retry path.",
468
+ INSUFFICIENT_FUNDS: "Payment method has insufficient funds. Prompt shopper to use another method.",
469
+ CARD_DECLINED: "Card was declined. Ask shopper to retry or switch payment method.",
470
+ INVALID_OTP: "Authorization code is invalid. Let shopper re-enter OTP/PIN and retry.",
471
+ OTP_EXPIRED: "Authorization code expired. Request a new OTP and re-submit authorization.",
472
+ AUTHORIZATION_FAILED: "Additional payment authorization failed. Retry authorization or change payment method.",
473
+ PAYMENT_ACTION_NOT_COMPLETED: "Required payment action was not completed. Resume provider flow and poll for status.",
474
+ SLOT_UNAVAILABLE: "Selected schedule slot is unavailable. Refresh available slots and ask shopper to reselect.",
475
+ BOOKING_CONFLICT: "The requested booking conflicts with an existing reservation. Pick another slot/resource.",
476
+ SERVICE_NOT_FOUND: "Requested service no longer exists. Refresh service catalogue and retry selection.",
477
+ OUT_OF_STOCK: "Inventory is depleted for this item. Remove it or reduce quantity before checkout.",
478
+ INSUFFICIENT_QUANTITY: "Requested quantity exceeds available inventory. Reduce quantity and retry.",
479
+ BUSINESS_ID_REQUIRED: "Business context could not be resolved. Verify the public key and business bootstrap call.",
480
+ INVALID_CART: "Cart is invalid for checkout. Sync cart state, ensure items exist, then retry.",
481
+ ORDER_TYPE_REQUIRED: "Order type is required. Provide one of delivery, pickup, or dine_in before checkout.",
482
+ NO_PAYMENT_ELEMENT: "PaymentElement is required for processCheckout(). Mount it before triggering checkout.",
483
+ PAYMENT_NOT_MOUNTED: "PaymentElement iframe is not mounted. Mount it in the DOM before processCheckout().",
484
+ AUTH_INCOMPLETE: "AuthElement has not completed authentication. Wait for AUTHENTICATED before checkout.",
485
+ AUTH_LOST: "Session was cleared during checkout. Re-authenticate and restart checkout safely.",
486
+ ALREADY_PROCESSING: "Checkout is already in progress. Disable duplicate submits until completion.",
487
+ CHECKOUT_NOT_READY: "Checkout elements are still initializing. Wait for readiness before submit.",
488
+ CANCELLED: "Checkout was cancelled. Preserve cart state and allow shopper to retry.",
489
+ REQUEST_TIMEOUT: "Provider call timed out. Poll payment/order status before issuing another charge attempt.",
490
+ POPUP_BLOCKED: "Browser blocked provider popup. Ask shopper to enable popups and retry.",
491
+ FX_QUOTE_FAILED: "Failed to lock FX quote. Retry currency quote or fallback to base currency."
492
+ };
493
+ var ERROR_HINTS = Object.fromEntries(
494
+ Object.entries(ERROR_SUGGESTIONS).map(([code, suggestion]) => [
495
+ code,
496
+ {
497
+ docs_url: docsUrlForCode(code),
498
+ suggestion
499
+ }
500
+ ])
501
+ );
502
+ var CimplifyError = class extends Error {
503
+ constructor(code, message, retryable = false, docs_url, suggestion) {
504
+ super(message);
505
+ this.code = code;
506
+ this.retryable = retryable;
507
+ this.docs_url = docs_url;
508
+ this.suggestion = suggestion;
509
+ this.name = "CimplifyError";
423
510
  }
424
- if (status === "preparing") {
425
- return "Preparing checkout";
511
+ /** User-friendly message safe to display */
512
+ get userMessage() {
513
+ return this.message;
426
514
  }
427
- if (status === "recovering") {
428
- return "Resuming payment";
515
+ };
516
+ function getErrorHint(code) {
517
+ return ERROR_HINTS[code];
518
+ }
519
+ function enrichError(error, options = {}) {
520
+ const hint = getErrorHint(error.code);
521
+ if (hint) {
522
+ if (!error.docs_url) {
523
+ error.docs_url = hint.docs_url;
524
+ }
525
+ if (!error.suggestion) {
526
+ error.suggestion = hint.suggestion;
527
+ }
528
+ } else if (!error.docs_url) {
529
+ error.docs_url = docsUrlForCode(error.code || ErrorCode.UNKNOWN_ERROR);
429
530
  }
430
- if (status === "processing") {
431
- return "Processing payment";
531
+ if (options.isTestMode && !error.message.includes("pk_test_")) {
532
+ error.message = `${error.message}
533
+
534
+ \u2139 Your API key is a test-mode key (pk_test_...). Verify test data/session before retrying.`;
432
535
  }
433
- if (status === "awaiting_authorization") {
434
- return "Waiting for authorization";
536
+ return error;
537
+ }
538
+
539
+ // src/types/result.ts
540
+ function ok(value) {
541
+ return { ok: true, value };
542
+ }
543
+ function err(error) {
544
+ return { ok: false, error };
545
+ }
546
+
547
+ // src/catalogue.ts
548
+ function toCimplifyError(error) {
549
+ if (error instanceof CimplifyError) return enrichError(error);
550
+ if (error instanceof Error) {
551
+ return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, error.message, false));
435
552
  }
436
- if (status === "polling") {
437
- return "Confirming payment";
553
+ return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, String(error), false));
554
+ }
555
+ async function safe(promise) {
556
+ try {
557
+ return ok(await promise);
558
+ } catch (error) {
559
+ return err(toCimplifyError(error));
438
560
  }
439
- if (status === "finalizing") {
440
- return "Finalizing order";
561
+ }
562
+ function withQuery(path, params) {
563
+ const query = new URLSearchParams();
564
+ for (const [key, value] of Object.entries(params)) {
565
+ if (value === void 0) continue;
566
+ query.set(key, String(value));
441
567
  }
442
- if (status === "success") {
443
- return "Payment complete";
568
+ const queryString = query.toString();
569
+ return queryString ? `${path}?${queryString}` : path;
570
+ }
571
+ function isRecord(value) {
572
+ return typeof value === "object" && value !== null;
573
+ }
574
+ function readFinalPrice(value) {
575
+ if (!isRecord(value)) return void 0;
576
+ const finalPrice = value.final_price;
577
+ if (typeof finalPrice === "string" || typeof finalPrice === "number") {
578
+ return finalPrice;
444
579
  }
445
- return "Payment failed";
446
- }
447
- function CimplifyCheckout({
448
- client,
449
- businessId,
450
- cartId,
451
- locationId,
452
- linkUrl,
453
- orderTypes,
454
- enrollInLink = true,
455
- onComplete,
456
- onError,
457
- onStatusChange,
458
- appearance,
459
- demoMode,
460
- className
461
- }) {
462
- const resolvedOrderTypes = React2.useMemo(
463
- () => orderTypes && orderTypes.length > 0 ? orderTypes : ["pickup", "delivery"],
464
- [orderTypes]
465
- );
466
- const [orderType, setOrderType] = React2.useState(resolvedOrderTypes[0] || "pickup");
467
- const [status, setStatus] = React2.useState(null);
468
- const [statusText, setStatusText] = React2.useState("");
469
- const [isSubmitting, setIsSubmitting] = React2.useState(false);
470
- const [isInitializing, setIsInitializing] = React2.useState(false);
471
- const [errorMessage, setErrorMessage] = React2.useState(null);
472
- const [resolvedBusinessId, setResolvedBusinessId] = React2.useState(businessId ?? null);
473
- const [resolvedCartId, setResolvedCartId] = React2.useState(cartId ?? null);
474
- const [resolvedCart, setResolvedCart] = React2.useState(null);
475
- const checkoutMountRef = React2.useRef(null);
476
- const elementsRef = React2.useRef(null);
477
- const activeCheckoutRef = React2.useRef(null);
478
- const initialAppearanceRef = React2.useRef(appearance);
479
- const hasWarnedInlineAppearanceRef = React2.useRef(false);
480
- const isMountedRef = React2.useRef(true);
481
- const demoRunRef = React2.useRef(0);
482
- const isDemoCheckout = demoMode ?? client.getPublicKey().trim().length === 0;
483
- const isTestMode = client.isTestMode();
484
- const primaryColor = appearance?.variables?.primaryColor || "#0a2540";
485
- const isDark = appearance?.theme === "dark";
486
- const emitStatus = React2__default.default.useEffectEvent(
487
- (nextStatus, context = {}) => {
488
- setStatus(nextStatus);
489
- setStatusText(context.display_text || "");
490
- onStatusChange?.(nextStatus, context);
491
- }
492
- );
493
- const fireError = React2__default.default.useEffectEvent(
494
- (error) => {
495
- onError?.(error);
496
- }
497
- );
498
- React2.useEffect(() => {
499
- if (!resolvedOrderTypes.includes(orderType)) {
500
- setOrderType(resolvedOrderTypes[0] || "pickup");
501
- }
502
- }, [resolvedOrderTypes, orderType]);
503
- React2.useEffect(() => {
504
- if (appearance && appearance !== initialAppearanceRef.current && !hasWarnedInlineAppearanceRef.current) {
505
- hasWarnedInlineAppearanceRef.current = true;
506
- console.warn(
507
- "[Cimplify] `appearance` prop reference changed after mount. Elements keep the initial appearance to avoid iframe remount. Memoize appearance with useMemo() to remove this warning."
508
- );
509
- }
510
- }, [appearance]);
511
- React2.useEffect(() => {
512
- let cancelled = false;
513
- async function bootstrap() {
514
- if (isDemoCheckout) {
515
- if (!cancelled) {
516
- setResolvedBusinessId(businessId ?? null);
517
- setResolvedCartId(cartId ?? "cart_demo");
518
- setIsInitializing(false);
519
- setErrorMessage(null);
520
- }
521
- return;
522
- }
523
- const needsBusinessResolve = !businessId;
524
- const needsCartResolve = !cartId;
525
- if (!needsBusinessResolve && !needsCartResolve) {
526
- if (!cancelled) {
527
- setResolvedBusinessId(businessId || null);
528
- setResolvedCartId(cartId || null);
529
- setIsInitializing(false);
530
- setErrorMessage(null);
531
- }
532
- client.cart.get().then((cartResult) => {
533
- if (!cancelled && cartResult.ok && cartResult.value) {
534
- setResolvedCart(cartResult.value);
535
- }
536
- }).catch(() => {
537
- });
538
- return;
539
- }
540
- if (!cancelled) {
541
- setIsInitializing(true);
542
- setErrorMessage(null);
543
- }
544
- let nextBusinessId = businessId ?? null;
545
- if (!nextBusinessId) {
546
- try {
547
- nextBusinessId = await client.resolveBusinessId();
548
- } catch {
549
- if (!cancelled) {
550
- const message = "Unable to initialize checkout business context.";
551
- setResolvedBusinessId(null);
552
- setResolvedCartId(null);
553
- setErrorMessage(message);
554
- setIsInitializing(false);
555
- fireError({ code: "BUSINESS_ID_REQUIRED", message });
556
- }
557
- return;
558
- }
559
- }
560
- let nextCartId = cartId ?? null;
561
- if (!nextCartId) {
562
- const cartResult = await client.cart.get();
563
- if (!cartResult.ok || !cartResult.value?.id || cartResult.value.items.length === 0) {
564
- if (!cancelled) {
565
- const message = "Your cart is empty. Add items before checkout.";
566
- setResolvedBusinessId(nextBusinessId);
567
- setResolvedCartId(null);
568
- setErrorMessage(message);
569
- setIsInitializing(false);
570
- fireError({ code: "CART_EMPTY", message });
571
- }
572
- return;
573
- }
574
- nextCartId = cartResult.value.id;
575
- if (!cancelled) {
576
- setResolvedCart(cartResult.value);
577
- }
578
- }
579
- if (!cancelled) {
580
- setResolvedBusinessId(nextBusinessId);
581
- setResolvedCartId(nextCartId);
582
- setIsInitializing(false);
583
- setErrorMessage(null);
584
- }
585
- }
586
- void bootstrap();
587
- return () => {
588
- cancelled = true;
589
- };
590
- }, [businessId, cartId, client, isDemoCheckout]);
591
- React2.useEffect(() => {
592
- return () => {
593
- isMountedRef.current = false;
594
- demoRunRef.current += 1;
595
- activeCheckoutRef.current?.abort();
596
- activeCheckoutRef.current = null;
597
- };
598
- }, []);
599
- const handleSubmit = React2__default.default.useEffectEvent(async () => {
600
- if (isSubmitting || isInitializing || !resolvedCartId) {
601
- if (!resolvedCartId && !isInitializing) {
602
- const message = "Your cart is empty. Add items before checkout.";
603
- setErrorMessage(message);
604
- fireError({ code: "CART_EMPTY", message });
605
- }
606
- return;
607
- }
608
- setErrorMessage(null);
609
- setIsSubmitting(true);
610
- emitStatus("preparing", { display_text: statusToLabel("preparing") });
611
- if (isDemoCheckout) {
612
- const runId = demoRunRef.current + 1;
613
- demoRunRef.current = runId;
614
- const wait = async (ms) => {
615
- await new Promise((resolve) => setTimeout(resolve, ms));
616
- return isMountedRef.current && runId === demoRunRef.current;
617
- };
618
- try {
619
- if (!await wait(400)) return;
620
- emitStatus("processing", { display_text: statusToLabel("processing") });
621
- if (!await wait(900)) return;
622
- emitStatus("polling", { display_text: statusToLabel("polling") });
623
- if (!await wait(1200)) return;
624
- const result = {
625
- success: true,
626
- order: {
627
- id: `ord_demo_${Date.now()}`,
628
- order_number: `DEMO-${Math.random().toString(36).slice(2, 8).toUpperCase()}`,
629
- status: "confirmed",
630
- total: "0.00",
631
- currency: "USD"
632
- }
633
- };
634
- emitStatus("success", {
635
- order_id: result.order?.id,
636
- order_number: result.order?.order_number,
637
- display_text: statusToLabel("success")
638
- });
639
- onComplete(result);
640
- } finally {
641
- if (isMountedRef.current && runId === demoRunRef.current) {
642
- setIsSubmitting(false);
643
- }
644
- }
645
- return;
646
- }
647
- if (!elementsRef.current) {
648
- const message = "Checkout is still initializing. Please try again.";
649
- setErrorMessage(message);
650
- fireError({ code: "CHECKOUT_NOT_READY", message });
651
- setIsSubmitting(false);
652
- return;
653
- }
654
- const checkout = elementsRef.current.processCheckout({
655
- cart_id: resolvedCartId,
656
- location_id: locationId ?? client.getLocationId() ?? void 0,
657
- order_type: orderType,
658
- enroll_in_link: enrollInLink,
659
- on_status_change: emitStatus
660
- });
661
- activeCheckoutRef.current = checkout;
662
- try {
663
- const result = await checkout;
664
- if (result.success) {
665
- onComplete(result);
666
- return;
667
- }
668
- const code = result.error?.code || "CHECKOUT_FAILED";
669
- const message = result.error?.message || "Payment failed.";
670
- setErrorMessage(message);
671
- fireError({ code, message });
672
- } finally {
673
- if (isMountedRef.current) {
674
- activeCheckoutRef.current = null;
675
- setIsSubmitting(false);
676
- }
677
- }
678
- });
679
- React2.useEffect(() => {
680
- if (isDemoCheckout || !resolvedBusinessId) {
681
- elementsRef.current = null;
682
- return;
683
- }
684
- const elements = client.elements(resolvedBusinessId, {
685
- appearance: initialAppearanceRef.current,
686
- linkUrl
687
- });
688
- elementsRef.current = elements;
689
- const checkout = elements.create("checkout", {
690
- orderTypes: resolvedOrderTypes,
691
- defaultOrderType: resolvedOrderTypes[0]
692
- });
693
- if (checkoutMountRef.current) {
694
- checkout.mount(checkoutMountRef.current);
695
- }
696
- checkout.on("ready", () => {
697
- if (resolvedCart) {
698
- checkout.setCart(transformToCheckoutCart(resolvedCart));
699
- }
700
- });
701
- checkout.on("order_type_changed", (data) => {
702
- const typed = data;
703
- if (typed.orderType) {
704
- setOrderType(typed.orderType);
705
- }
706
- });
707
- checkout.on("request_submit", () => {
708
- void handleSubmit();
709
- });
710
- return () => {
711
- activeCheckoutRef.current?.abort();
712
- activeCheckoutRef.current = null;
713
- elements.destroy();
714
- elementsRef.current = null;
715
- };
716
- }, [client, resolvedBusinessId, isDemoCheckout]);
717
- React2.useEffect(() => {
718
- if (!resolvedCart || !elementsRef.current) return;
719
- const checkoutElement = elementsRef.current.getElement("checkout");
720
- if (checkoutElement) {
721
- checkoutElement.setCart(transformToCheckoutCart(resolvedCart));
722
- }
723
- }, [resolvedCart]);
724
- const colors = shellColors(isDark ?? false, primaryColor);
725
- if (isInitializing) {
726
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className, "data-cimplify-checkout": "", children: /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-status": "", style: { fontSize: 13, color: colors.textSecondary }, children: "Preparing checkout..." }) });
727
- }
728
- if (!isDemoCheckout && (!resolvedBusinessId || !resolvedCartId)) {
729
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className, "data-cimplify-checkout": "", children: /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-error": "", style: { fontSize: 13, color: colors.error }, children: errorMessage || "Unable to initialize checkout. Please refresh and try again." }) });
730
- }
731
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, "data-cimplify-checkout": "", children: [
732
- isTestMode && !isDemoCheckout && /* @__PURE__ */ jsxRuntime.jsx(
733
- "p",
734
- {
735
- "data-cimplify-test-mode": "",
736
- style: {
737
- marginBottom: "10px",
738
- fontSize: "12px",
739
- fontWeight: 600,
740
- color: "#92400e"
741
- },
742
- children: "Test mode - no real charges"
743
- }
744
- ),
745
- /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-section": "checkout", children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: isDemoCheckout ? void 0 : checkoutMountRef }) }),
746
- status && /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-status": "", style: { marginTop: SPACE.sm, fontSize: 13, color: colors.textSecondary }, children: statusText || statusToLabel(status) }),
747
- errorMessage && /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-error": "", style: { marginTop: SPACE.sm, fontSize: 13, color: colors.error }, children: errorMessage })
748
- ] });
749
- }
750
-
751
- // src/utils/price.ts
752
- var CURRENCY_SYMBOLS = {
753
- // Major world currencies
754
- USD: "$",
755
- EUR: "\u20AC",
756
- GBP: "\xA3",
757
- JPY: "\xA5",
758
- CNY: "\xA5",
759
- CHF: "CHF",
760
- CAD: "C$",
761
- AUD: "A$",
762
- NZD: "NZ$",
763
- HKD: "HK$",
764
- SGD: "S$",
765
- INR: "\u20B9",
766
- BRL: "R$",
767
- MXN: "MX$",
768
- KRW: "\u20A9",
769
- RUB: "\u20BD",
770
- TRY: "\u20BA",
771
- THB: "\u0E3F",
772
- PLN: "z\u0142",
773
- SEK: "kr",
774
- NOK: "kr",
775
- DKK: "kr",
776
- CZK: "K\u010D",
777
- HUF: "Ft",
778
- ILS: "\u20AA",
779
- AED: "\u062F.\u0625",
780
- SAR: "\uFDFC",
781
- MYR: "RM",
782
- PHP: "\u20B1",
783
- IDR: "Rp",
784
- VND: "\u20AB",
785
- TWD: "NT$",
786
- // African currencies
787
- GHS: "GH\u20B5",
788
- NGN: "\u20A6",
789
- KES: "KSh",
790
- ZAR: "R",
791
- XOF: "CFA",
792
- XAF: "FCFA",
793
- EGP: "E\xA3",
794
- MAD: "MAD",
795
- TZS: "TSh",
796
- UGX: "USh",
797
- RWF: "FRw",
798
- ETB: "Br",
799
- ZMW: "ZK",
800
- BWP: "P",
801
- MUR: "\u20A8",
802
- SCR: "\u20A8",
803
- NAD: "N$",
804
- SZL: "E",
805
- LSL: "L",
806
- MWK: "MK",
807
- AOA: "Kz",
808
- CDF: "FC",
809
- GMD: "D",
810
- GNF: "FG",
811
- LRD: "L$",
812
- SLL: "Le",
813
- MZN: "MT",
814
- SDG: "SDG",
815
- SSP: "SSP",
816
- SOS: "Sh.So.",
817
- DJF: "Fdj",
818
- ERN: "Nfk",
819
- CVE: "$",
820
- STN: "Db",
821
- KMF: "CF",
822
- BIF: "FBu"
823
- };
824
- function getCurrencySymbol(currencyCode2) {
825
- return CURRENCY_SYMBOLS[currencyCode2.toUpperCase()] || currencyCode2;
826
- }
827
- function formatPrice(amount, currency = "GHS", locale = "en-US") {
828
- const numAmount = typeof amount === "string" ? parseFloat(amount) : amount;
829
- if (isNaN(numAmount)) {
830
- return `${getCurrencySymbol(currency)}0.00`;
831
- }
832
- try {
833
- return new Intl.NumberFormat(locale, {
834
- style: "currency",
835
- currency: currency.toUpperCase(),
836
- minimumFractionDigits: 2,
837
- maximumFractionDigits: 2
838
- }).format(numAmount);
839
- } catch {
840
- return `${getCurrencySymbol(currency)}${numAmount.toFixed(2)}`;
841
- }
842
- }
843
- function parsePrice(value) {
844
- if (value === void 0 || value === null) {
845
- return 0;
846
- }
847
- if (typeof value === "number") {
848
- return isNaN(value) ? 0 : value;
849
- }
850
- const cleaned = value.replace(/[^\d.-]/g, "");
851
- const parsed = parseFloat(cleaned);
852
- return isNaN(parsed) ? 0 : parsed;
853
- }
854
-
855
- // src/types/common.ts
856
- function money(value) {
857
- return value;
858
- }
859
- function moneyFromNumber(value) {
860
- return value.toFixed(2);
861
- }
862
- function currencyCode(value) {
863
- return value;
864
- }
865
- var ErrorCode = {
866
- // General
867
- UNKNOWN_ERROR: "UNKNOWN_ERROR",
868
- NETWORK_ERROR: "NETWORK_ERROR",
869
- TIMEOUT: "TIMEOUT",
870
- UNAUTHORIZED: "UNAUTHORIZED",
871
- NOT_FOUND: "NOT_FOUND"};
872
- var DOCS_ERROR_BASE_URL = "https://docs.cimplify.io/reference/error-codes";
873
- function docsUrlForCode(code) {
874
- return `${DOCS_ERROR_BASE_URL}#${code.toLowerCase().replace(/_/g, "-")}`;
875
- }
876
- var ERROR_SUGGESTIONS = {
877
- UNKNOWN_ERROR: "An unexpected error occurred. Capture the request/response payload and retry with exponential backoff.",
878
- NETWORK_ERROR: "Check the shopper's connection and retry. If this persists, inspect CORS, DNS, and API reachability.",
879
- TIMEOUT: "The request exceeded the timeout. Retry once, then poll order status before charging again.",
880
- UNAUTHORIZED: "Authentication is missing or expired. Ensure a valid access token is set and refresh the session if needed.",
881
- FORBIDDEN: "The key/session lacks permission for this resource. Verify business ownership and API key scope.",
882
- NOT_FOUND: "The requested resource does not exist or is not visible in this environment.",
883
- VALIDATION_ERROR: "One or more fields are invalid. Validate required fields and enum values before retrying.",
884
- CART_EMPTY: "The cart has no items. Redirect back to menu/catalogue and require at least one line item.",
885
- CART_EXPIRED: "This cart is no longer active. Recreate a new cart and re-add shopper selections.",
886
- CART_NOT_FOUND: "Cart could not be located. It may have expired or belongs to a different key/location.",
887
- ITEM_UNAVAILABLE: "The selected item is unavailable at this location/time. Prompt the shopper to pick an alternative.",
888
- VARIANT_NOT_FOUND: "The requested variant no longer exists. Refresh product data and require re-selection.",
889
- VARIANT_OUT_OF_STOCK: "The selected variant is out of stock. Show in-stock variants and block checkout for this line.",
890
- ADDON_REQUIRED: "A required add-on is missing. Ensure required modifier groups are completed before add-to-cart.",
891
- ADDON_MAX_EXCEEDED: "Too many add-ons were selected. Enforce max selections client-side before submission.",
892
- CHECKOUT_VALIDATION_FAILED: "Checkout payload failed validation. Verify customer, order type, and address fields are complete.",
893
- DELIVERY_ADDRESS_REQUIRED: "Delivery orders require an address. Collect and pass address info before processing checkout.",
894
- CUSTOMER_INFO_REQUIRED: "Customer details are required. Ensure name/email/phone are available before checkout.",
895
- QUOTE_NOT_FOUND: "Quote could not be found. Refresh pricing and create a new quote before checkout.",
896
- QUOTE_EXPIRED: "Quote has expired. Re-fetch pricing to generate a new quote with a valid expiry window.",
897
- QUOTE_CONSUMED: "Quote has already been used. Request a fresh quote to prevent duplicate checkout attempts.",
898
- QUOTE_STORAGE_UNAVAILABLE: "Quote storage is temporarily unavailable. Retry shortly and avoid charging until quote fetch succeeds.",
899
- PAYMENT_FAILED: "Payment provider rejected or failed processing. Show retry/change-method options to the shopper.",
900
- PAYMENT_CANCELLED: "Payment was cancelled by the shopper or provider flow. Allow a safe retry path.",
901
- INSUFFICIENT_FUNDS: "Payment method has insufficient funds. Prompt shopper to use another method.",
902
- CARD_DECLINED: "Card was declined. Ask shopper to retry or switch payment method.",
903
- INVALID_OTP: "Authorization code is invalid. Let shopper re-enter OTP/PIN and retry.",
904
- OTP_EXPIRED: "Authorization code expired. Request a new OTP and re-submit authorization.",
905
- AUTHORIZATION_FAILED: "Additional payment authorization failed. Retry authorization or change payment method.",
906
- PAYMENT_ACTION_NOT_COMPLETED: "Required payment action was not completed. Resume provider flow and poll for status.",
907
- SLOT_UNAVAILABLE: "Selected schedule slot is unavailable. Refresh available slots and ask shopper to reselect.",
908
- BOOKING_CONFLICT: "The requested booking conflicts with an existing reservation. Pick another slot/resource.",
909
- SERVICE_NOT_FOUND: "Requested service no longer exists. Refresh service catalogue and retry selection.",
910
- OUT_OF_STOCK: "Inventory is depleted for this item. Remove it or reduce quantity before checkout.",
911
- INSUFFICIENT_QUANTITY: "Requested quantity exceeds available inventory. Reduce quantity and retry.",
912
- BUSINESS_ID_REQUIRED: "Business context could not be resolved. Verify the public key and business bootstrap call.",
913
- INVALID_CART: "Cart is invalid for checkout. Sync cart state, ensure items exist, then retry.",
914
- ORDER_TYPE_REQUIRED: "Order type is required. Provide one of delivery, pickup, or dine_in before checkout.",
915
- NO_PAYMENT_ELEMENT: "PaymentElement is required for processCheckout(). Mount it before triggering checkout.",
916
- PAYMENT_NOT_MOUNTED: "PaymentElement iframe is not mounted. Mount it in the DOM before processCheckout().",
917
- AUTH_INCOMPLETE: "AuthElement has not completed authentication. Wait for AUTHENTICATED before checkout.",
918
- AUTH_LOST: "Session was cleared during checkout. Re-authenticate and restart checkout safely.",
919
- ALREADY_PROCESSING: "Checkout is already in progress. Disable duplicate submits until completion.",
920
- CHECKOUT_NOT_READY: "Checkout elements are still initializing. Wait for readiness before submit.",
921
- CANCELLED: "Checkout was cancelled. Preserve cart state and allow shopper to retry.",
922
- REQUEST_TIMEOUT: "Provider call timed out. Poll payment/order status before issuing another charge attempt.",
923
- POPUP_BLOCKED: "Browser blocked provider popup. Ask shopper to enable popups and retry.",
924
- FX_QUOTE_FAILED: "Failed to lock FX quote. Retry currency quote or fallback to base currency."
925
- };
926
- var ERROR_HINTS = Object.fromEntries(
927
- Object.entries(ERROR_SUGGESTIONS).map(([code, suggestion]) => [
928
- code,
929
- {
930
- docs_url: docsUrlForCode(code),
931
- suggestion
932
- }
933
- ])
934
- );
935
- var CimplifyError = class extends Error {
936
- constructor(code, message, retryable = false, docs_url, suggestion) {
937
- super(message);
938
- this.code = code;
939
- this.retryable = retryable;
940
- this.docs_url = docs_url;
941
- this.suggestion = suggestion;
942
- this.name = "CimplifyError";
943
- }
944
- /** User-friendly message safe to display */
945
- get userMessage() {
946
- return this.message;
947
- }
948
- };
949
- function getErrorHint(code) {
950
- return ERROR_HINTS[code];
951
- }
952
- function enrichError(error, options = {}) {
953
- const hint = getErrorHint(error.code);
954
- if (hint) {
955
- if (!error.docs_url) {
956
- error.docs_url = hint.docs_url;
957
- }
958
- if (!error.suggestion) {
959
- error.suggestion = hint.suggestion;
960
- }
961
- } else if (!error.docs_url) {
962
- error.docs_url = docsUrlForCode(error.code || ErrorCode.UNKNOWN_ERROR);
963
- }
964
- if (options.isTestMode && !error.message.includes("pk_test_")) {
965
- error.message = `${error.message}
966
-
967
- \u2139 Your API key is a test-mode key (pk_test_...). Verify test data/session before retrying.`;
968
- }
969
- return error;
970
- }
971
-
972
- // src/types/result.ts
973
- function ok(value) {
974
- return { ok: true, value };
975
- }
976
- function err(error) {
977
- return { ok: false, error };
978
- }
979
-
980
- // src/catalogue.ts
981
- function toCimplifyError(error) {
982
- if (error instanceof CimplifyError) return enrichError(error);
983
- if (error instanceof Error) {
984
- return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, error.message, false));
985
- }
986
- return enrichError(new CimplifyError(ErrorCode.UNKNOWN_ERROR, String(error), false));
987
- }
988
- async function safe(promise) {
989
- try {
990
- return ok(await promise);
991
- } catch (error) {
992
- return err(toCimplifyError(error));
993
- }
994
- }
995
- function withQuery(path, params) {
996
- const query = new URLSearchParams();
997
- for (const [key, value] of Object.entries(params)) {
998
- if (value === void 0) continue;
999
- query.set(key, String(value));
1000
- }
1001
- const queryString = query.toString();
1002
- return queryString ? `${path}?${queryString}` : path;
1003
- }
1004
- function isRecord(value) {
1005
- return typeof value === "object" && value !== null;
1006
- }
1007
- function readFinalPrice(value) {
1008
- if (!isRecord(value)) return void 0;
1009
- const finalPrice = value.final_price;
1010
- if (typeof finalPrice === "string" || typeof finalPrice === "number") {
1011
- return finalPrice;
1012
- }
1013
- return void 0;
580
+ return void 0;
1014
581
  }
1015
582
  function normalizeAddOnPayload(addOn) {
1016
583
  if (!isRecord(addOn)) return addOn;
@@ -1440,28 +1007,132 @@ var CartOperations = class {
1440
1007
  });
1441
1008
  return ok(found);
1442
1009
  }
1443
- async findItem(productId, variantId) {
1444
- const itemsResult = await this.getItems();
1445
- if (!itemsResult.ok) return itemsResult;
1446
- const found = itemsResult.value.find((item) => {
1447
- const matchesProduct = item.item_id === productId;
1448
- if (!variantId) return matchesProduct;
1449
- const config = item.configuration;
1450
- if ("variant" in config && config.variant) {
1451
- return matchesProduct && config.variant.variant_id === variantId;
1452
- }
1453
- return matchesProduct;
1454
- });
1455
- return ok(found);
1010
+ async findItem(productId, variantId) {
1011
+ const itemsResult = await this.getItems();
1012
+ if (!itemsResult.ok) return itemsResult;
1013
+ const found = itemsResult.value.find((item) => {
1014
+ const matchesProduct = item.item_id === productId;
1015
+ if (!variantId) return matchesProduct;
1016
+ const config = item.configuration;
1017
+ if ("variant" in config && config.variant) {
1018
+ return matchesProduct && config.variant.variant_id === variantId;
1019
+ }
1020
+ return matchesProduct;
1021
+ });
1022
+ return ok(found);
1023
+ }
1024
+ };
1025
+
1026
+ // src/constants.ts
1027
+ var MOBILE_MONEY_PROVIDER = {
1028
+ MTN: "mtn",
1029
+ VODAFONE: "vodafone",
1030
+ AIRTEL: "airtel"
1031
+ };
1032
+
1033
+ // src/utils/price.ts
1034
+ var CURRENCY_SYMBOLS = {
1035
+ // Major world currencies
1036
+ USD: "$",
1037
+ EUR: "\u20AC",
1038
+ GBP: "\xA3",
1039
+ JPY: "\xA5",
1040
+ CNY: "\xA5",
1041
+ CHF: "CHF",
1042
+ CAD: "C$",
1043
+ AUD: "A$",
1044
+ NZD: "NZ$",
1045
+ HKD: "HK$",
1046
+ SGD: "S$",
1047
+ INR: "\u20B9",
1048
+ BRL: "R$",
1049
+ MXN: "MX$",
1050
+ KRW: "\u20A9",
1051
+ RUB: "\u20BD",
1052
+ TRY: "\u20BA",
1053
+ THB: "\u0E3F",
1054
+ PLN: "z\u0142",
1055
+ SEK: "kr",
1056
+ NOK: "kr",
1057
+ DKK: "kr",
1058
+ CZK: "K\u010D",
1059
+ HUF: "Ft",
1060
+ ILS: "\u20AA",
1061
+ AED: "\u062F.\u0625",
1062
+ SAR: "\uFDFC",
1063
+ MYR: "RM",
1064
+ PHP: "\u20B1",
1065
+ IDR: "Rp",
1066
+ VND: "\u20AB",
1067
+ TWD: "NT$",
1068
+ // African currencies
1069
+ GHS: "GH\u20B5",
1070
+ NGN: "\u20A6",
1071
+ KES: "KSh",
1072
+ ZAR: "R",
1073
+ XOF: "CFA",
1074
+ XAF: "FCFA",
1075
+ EGP: "E\xA3",
1076
+ MAD: "MAD",
1077
+ TZS: "TSh",
1078
+ UGX: "USh",
1079
+ RWF: "FRw",
1080
+ ETB: "Br",
1081
+ ZMW: "ZK",
1082
+ BWP: "P",
1083
+ MUR: "\u20A8",
1084
+ SCR: "\u20A8",
1085
+ NAD: "N$",
1086
+ SZL: "E",
1087
+ LSL: "L",
1088
+ MWK: "MK",
1089
+ AOA: "Kz",
1090
+ CDF: "FC",
1091
+ GMD: "D",
1092
+ GNF: "FG",
1093
+ LRD: "L$",
1094
+ SLL: "Le",
1095
+ MZN: "MT",
1096
+ SDG: "SDG",
1097
+ SSP: "SSP",
1098
+ SOS: "Sh.So.",
1099
+ DJF: "Fdj",
1100
+ ERN: "Nfk",
1101
+ CVE: "$",
1102
+ STN: "Db",
1103
+ KMF: "CF",
1104
+ BIF: "FBu"
1105
+ };
1106
+ function getCurrencySymbol(currencyCode2) {
1107
+ return CURRENCY_SYMBOLS[currencyCode2.toUpperCase()] || currencyCode2;
1108
+ }
1109
+ function formatPrice(amount, currency = "GHS", locale = "en-US") {
1110
+ const numAmount = typeof amount === "string" ? parseFloat(amount) : amount;
1111
+ if (isNaN(numAmount)) {
1112
+ return `${getCurrencySymbol(currency)}0.00`;
1113
+ }
1114
+ try {
1115
+ return new Intl.NumberFormat(locale, {
1116
+ style: "currency",
1117
+ currency: currency.toUpperCase(),
1118
+ minimumFractionDigits: 2,
1119
+ maximumFractionDigits: 2
1120
+ }).format(numAmount);
1121
+ } catch {
1122
+ return `${getCurrencySymbol(currency)}${numAmount.toFixed(2)}`;
1123
+ }
1124
+ }
1125
+ function parsePrice(value) {
1126
+ if (value === void 0 || value === null) {
1127
+ return 0;
1456
1128
  }
1457
- };
1458
-
1459
- // src/constants.ts
1460
- var MOBILE_MONEY_PROVIDER = {
1461
- MTN: "mtn",
1462
- VODAFONE: "vodafone",
1463
- AIRTEL: "airtel"
1464
- };
1129
+ if (typeof value === "number") {
1130
+ return isNaN(value) ? 0 : value;
1131
+ }
1132
+ const cleaned = value.replace(/[^\d.-]/g, "");
1133
+ const parsed = parseFloat(cleaned);
1134
+ return isNaN(parsed) ? 0 : parsed;
1135
+ }
1465
1136
 
1466
1137
  // src/utils/payment.ts
1467
1138
  var PAYMENT_SUCCESS_STATUSES = /* @__PURE__ */ new Set([
@@ -3120,6 +2791,48 @@ var FxService = class {
3120
2791
  }
3121
2792
  };
3122
2793
 
2794
+ // src/types/elements.ts
2795
+ var ELEMENT_TYPES = {
2796
+ AUTH: "auth",
2797
+ ADDRESS: "address",
2798
+ PAYMENT: "payment",
2799
+ CHECKOUT: "checkout"
2800
+ };
2801
+ var MESSAGE_TYPES = {
2802
+ // Parent → Iframe
2803
+ INIT: "init",
2804
+ SET_TOKEN: "set_token",
2805
+ SET_CART: "set_cart",
2806
+ GET_DATA: "get_data",
2807
+ PROCESS_CHECKOUT: "process_checkout",
2808
+ ABORT_CHECKOUT: "abort_checkout",
2809
+ // Iframe → Parent
2810
+ READY: "ready",
2811
+ HEIGHT_CHANGE: "height_change",
2812
+ AUTHENTICATED: "authenticated",
2813
+ REQUIRES_OTP: "requires_otp",
2814
+ ERROR: "error",
2815
+ ADDRESS_CHANGED: "address_changed",
2816
+ ADDRESS_SELECTED: "address_selected",
2817
+ PAYMENT_METHOD_SELECTED: "payment_method_selected",
2818
+ TOKEN_REFRESHED: "token_refreshed",
2819
+ LOGOUT_COMPLETE: "logout_complete",
2820
+ CONTACT_PROVIDED: "contact_provided",
2821
+ CHECKOUT_STATUS: "checkout_status",
2822
+ CHECKOUT_COMPLETE: "checkout_complete",
2823
+ ORDER_TYPE_CHANGED: "order_type_changed",
2824
+ REQUEST_SUBMIT: "request_submit"
2825
+ };
2826
+ var EVENT_TYPES = {
2827
+ READY: "ready",
2828
+ AUTHENTICATED: "authenticated",
2829
+ REQUIRES_OTP: "requires_otp",
2830
+ ERROR: "error",
2831
+ CHANGE: "change",
2832
+ ORDER_TYPE_CHANGED: "order_type_changed",
2833
+ REQUEST_SUBMIT: "request_submit"
2834
+ };
2835
+
3123
2836
  // src/elements.ts
3124
2837
  function toCheckoutError(code, message, recoverable) {
3125
2838
  const hint = getErrorHint(code);
@@ -4406,247 +4119,610 @@ var CimplifyClient = class {
4406
4119
  }
4407
4120
  return createElements(this, businessId ?? this.businessId ?? void 0, options);
4408
4121
  }
4409
- };
4410
- function createCimplifyClient(config = {}) {
4411
- return new CimplifyClient(config);
4122
+ };
4123
+ function createCimplifyClient(config = {}) {
4124
+ return new CimplifyClient(config);
4125
+ }
4126
+ var LOCATION_STORAGE_KEY = "cimplify_location_id";
4127
+ var DISPLAY_CURRENCY_STORAGE_KEY = "cimplify_display_currency";
4128
+ var FX_REFRESH_INTERVAL = 12e4;
4129
+ var DEFAULT_CURRENCY = "USD";
4130
+ var DEFAULT_COUNTRY = "US";
4131
+ function createDefaultClient() {
4132
+ const processRef = globalThis.process;
4133
+ const envPublicKey = processRef?.env?.NEXT_PUBLIC_CIMPLIFY_PUBLIC_KEY || "";
4134
+ return createCimplifyClient({ publicKey: envPublicKey });
4135
+ }
4136
+ function getStoredLocationId() {
4137
+ if (typeof window === "undefined" || !window.localStorage) {
4138
+ return null;
4139
+ }
4140
+ const value = window.localStorage.getItem(LOCATION_STORAGE_KEY);
4141
+ if (!value) {
4142
+ return null;
4143
+ }
4144
+ const normalized = value.trim();
4145
+ return normalized.length > 0 ? normalized : null;
4146
+ }
4147
+ function setStoredLocationId(locationId) {
4148
+ if (typeof window === "undefined" || !window.localStorage) {
4149
+ return;
4150
+ }
4151
+ if (!locationId) {
4152
+ window.localStorage.removeItem(LOCATION_STORAGE_KEY);
4153
+ return;
4154
+ }
4155
+ window.localStorage.setItem(LOCATION_STORAGE_KEY, locationId);
4156
+ }
4157
+ function getStoredDisplayCurrency() {
4158
+ if (typeof window === "undefined" || !window.localStorage) {
4159
+ return null;
4160
+ }
4161
+ const value = window.localStorage.getItem(DISPLAY_CURRENCY_STORAGE_KEY);
4162
+ if (!value) {
4163
+ return null;
4164
+ }
4165
+ const normalized = value.trim().toUpperCase();
4166
+ return normalized.length > 0 ? normalized : null;
4167
+ }
4168
+ function setStoredDisplayCurrency(currency) {
4169
+ if (typeof window === "undefined" || !window.localStorage) {
4170
+ return;
4171
+ }
4172
+ if (!currency) {
4173
+ window.localStorage.removeItem(DISPLAY_CURRENCY_STORAGE_KEY);
4174
+ return;
4175
+ }
4176
+ window.localStorage.setItem(DISPLAY_CURRENCY_STORAGE_KEY, currency.toUpperCase());
4177
+ }
4178
+ function resolveInitialLocation(locations) {
4179
+ if (locations.length === 0) {
4180
+ return null;
4181
+ }
4182
+ const storedId = getStoredLocationId();
4183
+ if (storedId) {
4184
+ const matched = locations.find((location) => location.id === storedId);
4185
+ if (matched) {
4186
+ return matched;
4187
+ }
4188
+ }
4189
+ return locations[0];
4190
+ }
4191
+ var CimplifyContext = React3.createContext(null);
4192
+ function CimplifyProvider({
4193
+ client,
4194
+ children,
4195
+ onLocationChange
4196
+ }) {
4197
+ const resolvedClient = React3.useMemo(() => client ?? createDefaultClient(), [client]);
4198
+ const onLocationChangeRef = React3.useRef(onLocationChange);
4199
+ const [business, setBusiness] = React3.useState(null);
4200
+ const [locations, setLocations] = React3.useState([]);
4201
+ const [currentLocation, setCurrentLocationState] = React3.useState(null);
4202
+ const [isReady, setIsReady] = React3.useState(false);
4203
+ React3.useEffect(() => {
4204
+ onLocationChangeRef.current = onLocationChange;
4205
+ }, [onLocationChange]);
4206
+ const isDemoMode = resolvedClient.getPublicKey().trim().length === 0;
4207
+ const baseCurrency = business?.default_currency || DEFAULT_CURRENCY;
4208
+ const [displayCurrencyOverride, setDisplayCurrencyOverride] = React3.useState(
4209
+ () => getStoredDisplayCurrency()
4210
+ );
4211
+ const [fxRate, setFxRate] = React3.useState(null);
4212
+ const displayCurrency = displayCurrencyOverride && displayCurrencyOverride !== baseCurrency ? displayCurrencyOverride : baseCurrency;
4213
+ const setDisplayCurrency = React3.useCallback(
4214
+ (currency) => {
4215
+ const normalized = currency?.trim().toUpperCase() || null;
4216
+ if (normalized && !isSupportedCurrency(normalized)) {
4217
+ return;
4218
+ }
4219
+ setDisplayCurrencyOverride(normalized);
4220
+ setStoredDisplayCurrency(normalized);
4221
+ if (!normalized || normalized === baseCurrency) {
4222
+ setFxRate(null);
4223
+ }
4224
+ },
4225
+ [baseCurrency]
4226
+ );
4227
+ React3.useEffect(() => {
4228
+ if (displayCurrency === baseCurrency || isDemoMode) {
4229
+ setFxRate(null);
4230
+ return;
4231
+ }
4232
+ let cancelled = false;
4233
+ async function fetchRate() {
4234
+ const result = await resolvedClient.fx.getRate(
4235
+ baseCurrency,
4236
+ displayCurrency
4237
+ );
4238
+ if (cancelled) return;
4239
+ if (result.ok) {
4240
+ setFxRate(result.value.rate);
4241
+ } else {
4242
+ setFxRate(null);
4243
+ }
4244
+ }
4245
+ void fetchRate();
4246
+ const intervalId = setInterval(() => void fetchRate(), FX_REFRESH_INTERVAL);
4247
+ return () => {
4248
+ cancelled = true;
4249
+ clearInterval(intervalId);
4250
+ };
4251
+ }, [resolvedClient, baseCurrency, displayCurrency, isDemoMode]);
4252
+ const convertPrice = React3.useCallback(
4253
+ (amount) => {
4254
+ const num = typeof amount === "string" ? parseFloat(amount) : amount;
4255
+ if (isNaN(num)) return 0;
4256
+ if (!fxRate || displayCurrency === baseCurrency) return num;
4257
+ return Math.round(num * fxRate * 100) / 100;
4258
+ },
4259
+ [fxRate, displayCurrency, baseCurrency]
4260
+ );
4261
+ const setCurrentLocation = React3.useCallback(
4262
+ (location) => {
4263
+ setCurrentLocationState(location);
4264
+ resolvedClient.setLocationId(location.id);
4265
+ setStoredLocationId(location.id);
4266
+ onLocationChangeRef.current?.(location);
4267
+ },
4268
+ [resolvedClient]
4269
+ );
4270
+ React3.useEffect(() => {
4271
+ let cancelled = false;
4272
+ async function bootstrap() {
4273
+ setIsReady(false);
4274
+ if (isDemoMode) {
4275
+ if (!cancelled) {
4276
+ setBusiness(null);
4277
+ setLocations([]);
4278
+ setCurrentLocationState(null);
4279
+ resolvedClient.setLocationId(null);
4280
+ setStoredLocationId(null);
4281
+ setIsReady(true);
4282
+ }
4283
+ return;
4284
+ }
4285
+ const [businessResult, locationsResult] = await Promise.all([
4286
+ resolvedClient.business.getInfo(),
4287
+ resolvedClient.business.getLocations()
4288
+ ]);
4289
+ if (cancelled) {
4290
+ return;
4291
+ }
4292
+ const nextBusiness = businessResult.ok ? businessResult.value : null;
4293
+ const nextLocations = locationsResult.ok && Array.isArray(locationsResult.value) ? locationsResult.value : [];
4294
+ const initialLocation = resolveInitialLocation(nextLocations);
4295
+ setBusiness(nextBusiness);
4296
+ if (nextBusiness?.id) {
4297
+ resolvedClient.setBusinessId(nextBusiness.id);
4298
+ }
4299
+ setLocations(nextLocations);
4300
+ if (initialLocation) {
4301
+ setCurrentLocationState(initialLocation);
4302
+ resolvedClient.setLocationId(initialLocation.id);
4303
+ setStoredLocationId(initialLocation.id);
4304
+ } else {
4305
+ setCurrentLocationState(null);
4306
+ resolvedClient.setLocationId(null);
4307
+ setStoredLocationId(null);
4308
+ }
4309
+ setIsReady(true);
4310
+ }
4311
+ bootstrap().catch(() => {
4312
+ if (cancelled) {
4313
+ return;
4314
+ }
4315
+ setBusiness(null);
4316
+ setLocations([]);
4317
+ setCurrentLocationState(null);
4318
+ resolvedClient.setLocationId(null);
4319
+ setStoredLocationId(null);
4320
+ setIsReady(true);
4321
+ });
4322
+ return () => {
4323
+ cancelled = true;
4324
+ };
4325
+ }, [resolvedClient, isDemoMode]);
4326
+ const contextValue = React3.useMemo(
4327
+ () => ({
4328
+ client: resolvedClient,
4329
+ business,
4330
+ currency: baseCurrency,
4331
+ country: business?.country_code || DEFAULT_COUNTRY,
4332
+ locations,
4333
+ currentLocation,
4334
+ setCurrentLocation,
4335
+ isReady,
4336
+ isDemoMode,
4337
+ baseCurrency,
4338
+ displayCurrency,
4339
+ setDisplayCurrency,
4340
+ convertPrice,
4341
+ fxRate
4342
+ }),
4343
+ [
4344
+ resolvedClient,
4345
+ business,
4346
+ baseCurrency,
4347
+ locations,
4348
+ currentLocation,
4349
+ setCurrentLocation,
4350
+ isReady,
4351
+ isDemoMode,
4352
+ displayCurrency,
4353
+ setDisplayCurrency,
4354
+ convertPrice,
4355
+ fxRate
4356
+ ]
4357
+ );
4358
+ return /* @__PURE__ */ jsxRuntime.jsx(CimplifyContext.Provider, { value: contextValue, children });
4359
+ }
4360
+ function useCimplify() {
4361
+ const context = React3.useContext(CimplifyContext);
4362
+ if (!context) {
4363
+ throw new Error("useCimplify must be used within CimplifyProvider");
4364
+ }
4365
+ return context;
4412
4366
  }
4413
- var LOCATION_STORAGE_KEY = "cimplify_location_id";
4414
- var DISPLAY_CURRENCY_STORAGE_KEY = "cimplify_display_currency";
4415
- var FX_REFRESH_INTERVAL = 12e4;
4416
- var DEFAULT_CURRENCY = "USD";
4417
- var DEFAULT_COUNTRY = "US";
4418
- function createDefaultClient() {
4419
- const processRef = globalThis.process;
4420
- const envPublicKey = processRef?.env?.NEXT_PUBLIC_CIMPLIFY_PUBLIC_KEY || "";
4421
- return createCimplifyClient({ publicKey: envPublicKey });
4367
+ function useOptionalCimplify() {
4368
+ return React3.useContext(CimplifyContext);
4422
4369
  }
4423
- function getStoredLocationId() {
4424
- if (typeof window === "undefined" || !window.localStorage) {
4425
- return null;
4426
- }
4427
- const value = window.localStorage.getItem(LOCATION_STORAGE_KEY);
4428
- if (!value) {
4429
- return null;
4430
- }
4431
- const normalized = value.trim();
4432
- return normalized.length > 0 ? normalized : null;
4370
+ var SPACE = { sm: 8};
4371
+ function shellColors(isDark, primaryColor) {
4372
+ return {
4373
+ text: isDark ? "#f4f4f5" : "#1a1a1a",
4374
+ textSecondary: isDark ? "#a1a1aa" : "#52525b",
4375
+ textMuted: isDark ? "#71717a" : "#a1a1aa",
4376
+ border: isDark ? "#27272a" : "#e4e4e7",
4377
+ surface: isDark ? "#18181b" : "#fafafa",
4378
+ error: "#dc2626",
4379
+ primary: primaryColor
4380
+ };
4433
4381
  }
4434
- function setStoredLocationId(locationId) {
4435
- if (typeof window === "undefined" || !window.localStorage) {
4436
- return;
4382
+ function statusToLabel(status) {
4383
+ if (!status) {
4384
+ return "";
4437
4385
  }
4438
- if (!locationId) {
4439
- window.localStorage.removeItem(LOCATION_STORAGE_KEY);
4440
- return;
4386
+ if (status === "preparing") {
4387
+ return "Preparing checkout";
4441
4388
  }
4442
- window.localStorage.setItem(LOCATION_STORAGE_KEY, locationId);
4443
- }
4444
- function getStoredDisplayCurrency() {
4445
- if (typeof window === "undefined" || !window.localStorage) {
4446
- return null;
4389
+ if (status === "recovering") {
4390
+ return "Resuming payment";
4447
4391
  }
4448
- const value = window.localStorage.getItem(DISPLAY_CURRENCY_STORAGE_KEY);
4449
- if (!value) {
4450
- return null;
4392
+ if (status === "processing") {
4393
+ return "Processing payment";
4451
4394
  }
4452
- const normalized = value.trim().toUpperCase();
4453
- return normalized.length > 0 ? normalized : null;
4454
- }
4455
- function setStoredDisplayCurrency(currency) {
4456
- if (typeof window === "undefined" || !window.localStorage) {
4457
- return;
4395
+ if (status === "awaiting_authorization") {
4396
+ return "Waiting for authorization";
4458
4397
  }
4459
- if (!currency) {
4460
- window.localStorage.removeItem(DISPLAY_CURRENCY_STORAGE_KEY);
4461
- return;
4398
+ if (status === "polling") {
4399
+ return "Confirming payment";
4462
4400
  }
4463
- window.localStorage.setItem(DISPLAY_CURRENCY_STORAGE_KEY, currency.toUpperCase());
4464
- }
4465
- function resolveInitialLocation(locations) {
4466
- if (locations.length === 0) {
4467
- return null;
4401
+ if (status === "finalizing") {
4402
+ return "Finalizing order";
4468
4403
  }
4469
- const storedId = getStoredLocationId();
4470
- if (storedId) {
4471
- const matched = locations.find((location) => location.id === storedId);
4472
- if (matched) {
4473
- return matched;
4474
- }
4404
+ if (status === "success") {
4405
+ return "Payment complete";
4475
4406
  }
4476
- return locations[0];
4407
+ return "Payment failed";
4477
4408
  }
4478
- var CimplifyContext = React2.createContext(null);
4479
- function CimplifyProvider({
4409
+ function CimplifyCheckout({
4480
4410
  client,
4481
- children,
4482
- onLocationChange
4411
+ businessId,
4412
+ cartId,
4413
+ locationId,
4414
+ linkUrl,
4415
+ orderTypes,
4416
+ enrollInLink = true,
4417
+ onComplete,
4418
+ onError,
4419
+ onStatusChange,
4420
+ appearance,
4421
+ demoMode,
4422
+ className
4483
4423
  }) {
4484
- const resolvedClient = React2.useMemo(() => client ?? createDefaultClient(), [client]);
4485
- const onLocationChangeRef = React2.useRef(onLocationChange);
4486
- const [business, setBusiness] = React2.useState(null);
4487
- const [locations, setLocations] = React2.useState([]);
4488
- const [currentLocation, setCurrentLocationState] = React2.useState(null);
4489
- const [isReady, setIsReady] = React2.useState(false);
4490
- React2.useEffect(() => {
4491
- onLocationChangeRef.current = onLocationChange;
4492
- }, [onLocationChange]);
4493
- const isDemoMode = resolvedClient.getPublicKey().trim().length === 0;
4494
- const baseCurrency = business?.default_currency || DEFAULT_CURRENCY;
4495
- const [displayCurrencyOverride, setDisplayCurrencyOverride] = React2.useState(
4496
- () => getStoredDisplayCurrency()
4424
+ const resolvedOrderTypes = React3.useMemo(
4425
+ () => orderTypes && orderTypes.length > 0 ? orderTypes : ["pickup", "delivery"],
4426
+ [orderTypes]
4497
4427
  );
4498
- const [fxRate, setFxRate] = React2.useState(null);
4499
- const displayCurrency = displayCurrencyOverride && displayCurrencyOverride !== baseCurrency ? displayCurrencyOverride : baseCurrency;
4500
- const setDisplayCurrency = React2.useCallback(
4501
- (currency) => {
4502
- const normalized = currency?.trim().toUpperCase() || null;
4503
- setDisplayCurrencyOverride(normalized);
4504
- setStoredDisplayCurrency(normalized);
4505
- if (!normalized || normalized === baseCurrency) {
4506
- setFxRate(null);
4507
- }
4508
- },
4509
- [baseCurrency]
4428
+ const [orderType, setOrderType] = React3.useState(resolvedOrderTypes[0] || "pickup");
4429
+ const [status, setStatus] = React3.useState(null);
4430
+ const [statusText, setStatusText] = React3.useState("");
4431
+ const [isSubmitting, setIsSubmitting] = React3.useState(false);
4432
+ const [isInitializing, setIsInitializing] = React3.useState(false);
4433
+ const [errorMessage, setErrorMessage] = React3.useState(null);
4434
+ const [resolvedBusinessId, setResolvedBusinessId] = React3.useState(businessId ?? null);
4435
+ const [resolvedCartId, setResolvedCartId] = React3.useState(cartId ?? null);
4436
+ const [resolvedCart, setResolvedCart] = React3.useState(null);
4437
+ const checkoutMountRef = React3.useRef(null);
4438
+ const elementsRef = React3.useRef(null);
4439
+ const activeCheckoutRef = React3.useRef(null);
4440
+ const initialAppearanceRef = React3.useRef(appearance);
4441
+ const hasWarnedInlineAppearanceRef = React3.useRef(false);
4442
+ const isMountedRef = React3.useRef(true);
4443
+ const demoRunRef = React3.useRef(0);
4444
+ const isDemoCheckout = demoMode ?? client.getPublicKey().trim().length === 0;
4445
+ const isTestMode = client.isTestMode();
4446
+ const cimplifyCtx = useOptionalCimplify();
4447
+ const fxOptions = React3.useMemo(() => {
4448
+ if (!cimplifyCtx?.fxRate) return void 0;
4449
+ if (cimplifyCtx.displayCurrency === cimplifyCtx.baseCurrency) return void 0;
4450
+ return {
4451
+ displayCurrency: cimplifyCtx.displayCurrency,
4452
+ convertPrice: cimplifyCtx.convertPrice
4453
+ };
4454
+ }, [cimplifyCtx?.fxRate, cimplifyCtx?.displayCurrency, cimplifyCtx?.baseCurrency, cimplifyCtx?.convertPrice]);
4455
+ const fxOptionsRef = React3.useRef(fxOptions);
4456
+ fxOptionsRef.current = fxOptions;
4457
+ const resolvedCartRef = React3.useRef(resolvedCart);
4458
+ resolvedCartRef.current = resolvedCart;
4459
+ const primaryColor = appearance?.variables?.primaryColor || "#0a2540";
4460
+ const isDark = appearance?.theme === "dark";
4461
+ const emitStatus = React3__default.default.useEffectEvent(
4462
+ (nextStatus, context = {}) => {
4463
+ setStatus(nextStatus);
4464
+ setStatusText(context.display_text || "");
4465
+ onStatusChange?.(nextStatus, context);
4466
+ }
4510
4467
  );
4511
- React2.useEffect(() => {
4512
- if (displayCurrency === baseCurrency || isDemoMode) {
4513
- setFxRate(null);
4514
- return;
4468
+ const fireError = React3__default.default.useEffectEvent(
4469
+ (error) => {
4470
+ onError?.(error);
4515
4471
  }
4516
- let cancelled = false;
4517
- async function fetchRate() {
4518
- const result = await resolvedClient.fx.getRate(
4519
- baseCurrency,
4520
- displayCurrency
4472
+ );
4473
+ React3.useEffect(() => {
4474
+ if (!resolvedOrderTypes.includes(orderType)) {
4475
+ setOrderType(resolvedOrderTypes[0] || "pickup");
4476
+ }
4477
+ }, [resolvedOrderTypes, orderType]);
4478
+ React3.useEffect(() => {
4479
+ if (appearance && appearance !== initialAppearanceRef.current && !hasWarnedInlineAppearanceRef.current) {
4480
+ hasWarnedInlineAppearanceRef.current = true;
4481
+ console.warn(
4482
+ "[Cimplify] `appearance` prop reference changed after mount. Elements keep the initial appearance to avoid iframe remount. Memoize appearance with useMemo() to remove this warning."
4521
4483
  );
4522
- if (!cancelled && result.ok) {
4523
- setFxRate(result.value.rate);
4484
+ }
4485
+ }, [appearance]);
4486
+ React3.useEffect(() => {
4487
+ let cancelled = false;
4488
+ async function bootstrap() {
4489
+ if (isDemoCheckout) {
4490
+ if (!cancelled) {
4491
+ setResolvedBusinessId(businessId ?? null);
4492
+ setResolvedCartId(cartId ?? "cart_demo");
4493
+ setIsInitializing(false);
4494
+ setErrorMessage(null);
4495
+ }
4496
+ return;
4497
+ }
4498
+ const needsBusinessResolve = !businessId;
4499
+ const needsCartResolve = !cartId;
4500
+ if (!needsBusinessResolve && !needsCartResolve) {
4501
+ if (!cancelled) {
4502
+ setResolvedBusinessId(businessId || null);
4503
+ setResolvedCartId(cartId || null);
4504
+ setIsInitializing(false);
4505
+ setErrorMessage(null);
4506
+ }
4507
+ client.cart.get().then((cartResult) => {
4508
+ if (!cancelled && cartResult.ok && cartResult.value) {
4509
+ setResolvedCart(cartResult.value);
4510
+ }
4511
+ }).catch(() => {
4512
+ });
4513
+ return;
4514
+ }
4515
+ if (!cancelled) {
4516
+ setIsInitializing(true);
4517
+ setErrorMessage(null);
4518
+ }
4519
+ let nextBusinessId = businessId ?? null;
4520
+ if (!nextBusinessId) {
4521
+ try {
4522
+ nextBusinessId = await client.resolveBusinessId();
4523
+ } catch {
4524
+ if (!cancelled) {
4525
+ const message = "Unable to initialize checkout business context.";
4526
+ setResolvedBusinessId(null);
4527
+ setResolvedCartId(null);
4528
+ setErrorMessage(message);
4529
+ setIsInitializing(false);
4530
+ fireError({ code: "BUSINESS_ID_REQUIRED", message });
4531
+ }
4532
+ return;
4533
+ }
4534
+ }
4535
+ let nextCartId = cartId ?? null;
4536
+ if (!nextCartId) {
4537
+ const cartResult = await client.cart.get();
4538
+ if (!cartResult.ok || !cartResult.value?.id || cartResult.value.items.length === 0) {
4539
+ if (!cancelled) {
4540
+ const message = "Your cart is empty. Add items before checkout.";
4541
+ setResolvedBusinessId(nextBusinessId);
4542
+ setResolvedCartId(null);
4543
+ setErrorMessage(message);
4544
+ setIsInitializing(false);
4545
+ fireError({ code: "CART_EMPTY", message });
4546
+ }
4547
+ return;
4548
+ }
4549
+ nextCartId = cartResult.value.id;
4550
+ if (!cancelled) {
4551
+ setResolvedCart(cartResult.value);
4552
+ }
4553
+ }
4554
+ if (!cancelled) {
4555
+ setResolvedBusinessId(nextBusinessId);
4556
+ setResolvedCartId(nextCartId);
4557
+ setIsInitializing(false);
4558
+ setErrorMessage(null);
4524
4559
  }
4525
4560
  }
4526
- void fetchRate();
4527
- const intervalId = setInterval(() => void fetchRate(), FX_REFRESH_INTERVAL);
4561
+ void bootstrap();
4528
4562
  return () => {
4529
4563
  cancelled = true;
4530
- clearInterval(intervalId);
4531
4564
  };
4532
- }, [resolvedClient, baseCurrency, displayCurrency, isDemoMode]);
4533
- const convertPrice = React2.useCallback(
4534
- (amount) => {
4535
- const num = typeof amount === "string" ? parseFloat(amount) : amount;
4536
- if (isNaN(num)) return 0;
4537
- if (!fxRate || displayCurrency === baseCurrency) return num;
4538
- return Math.round(num * fxRate * 100) / 100;
4539
- },
4540
- [fxRate, displayCurrency, baseCurrency]
4541
- );
4542
- const setCurrentLocation = React2.useCallback(
4543
- (location) => {
4544
- setCurrentLocationState(location);
4545
- resolvedClient.setLocationId(location.id);
4546
- setStoredLocationId(location.id);
4547
- onLocationChangeRef.current?.(location);
4548
- },
4549
- [resolvedClient]
4550
- );
4551
- React2.useEffect(() => {
4552
- let cancelled = false;
4553
- async function bootstrap() {
4554
- setIsReady(false);
4555
- if (isDemoMode) {
4556
- if (!cancelled) {
4557
- setBusiness(null);
4558
- setLocations([]);
4559
- setCurrentLocationState(null);
4560
- resolvedClient.setLocationId(null);
4561
- setStoredLocationId(null);
4562
- setIsReady(true);
4565
+ }, [businessId, cartId, client, isDemoCheckout]);
4566
+ React3.useEffect(() => {
4567
+ return () => {
4568
+ isMountedRef.current = false;
4569
+ demoRunRef.current += 1;
4570
+ activeCheckoutRef.current?.abort();
4571
+ activeCheckoutRef.current = null;
4572
+ };
4573
+ }, []);
4574
+ const handleSubmit = React3__default.default.useEffectEvent(async () => {
4575
+ if (isSubmitting || isInitializing || !resolvedCartId) {
4576
+ if (!resolvedCartId && !isInitializing) {
4577
+ const message = "Your cart is empty. Add items before checkout.";
4578
+ setErrorMessage(message);
4579
+ fireError({ code: "CART_EMPTY", message });
4580
+ }
4581
+ return;
4582
+ }
4583
+ setErrorMessage(null);
4584
+ setIsSubmitting(true);
4585
+ emitStatus("preparing", { display_text: statusToLabel("preparing") });
4586
+ if (isDemoCheckout) {
4587
+ const runId = demoRunRef.current + 1;
4588
+ demoRunRef.current = runId;
4589
+ const wait = async (ms) => {
4590
+ await new Promise((resolve) => setTimeout(resolve, ms));
4591
+ return isMountedRef.current && runId === demoRunRef.current;
4592
+ };
4593
+ try {
4594
+ if (!await wait(400)) return;
4595
+ emitStatus("processing", { display_text: statusToLabel("processing") });
4596
+ if (!await wait(900)) return;
4597
+ emitStatus("polling", { display_text: statusToLabel("polling") });
4598
+ if (!await wait(1200)) return;
4599
+ const result = {
4600
+ success: true,
4601
+ order: {
4602
+ id: `ord_demo_${Date.now()}`,
4603
+ order_number: `DEMO-${Math.random().toString(36).slice(2, 8).toUpperCase()}`,
4604
+ status: "confirmed",
4605
+ total: "0.00",
4606
+ currency: "USD"
4607
+ }
4608
+ };
4609
+ emitStatus("success", {
4610
+ order_id: result.order?.id,
4611
+ order_number: result.order?.order_number,
4612
+ display_text: statusToLabel("success")
4613
+ });
4614
+ onComplete(result);
4615
+ } finally {
4616
+ if (isMountedRef.current && runId === demoRunRef.current) {
4617
+ setIsSubmitting(false);
4563
4618
  }
4564
- return;
4565
4619
  }
4566
- const [businessResult, locationsResult] = await Promise.all([
4567
- resolvedClient.business.getInfo(),
4568
- resolvedClient.business.getLocations()
4569
- ]);
4570
- if (cancelled) {
4620
+ return;
4621
+ }
4622
+ if (!elementsRef.current) {
4623
+ const message = "Checkout is still initializing. Please try again.";
4624
+ setErrorMessage(message);
4625
+ fireError({ code: "CHECKOUT_NOT_READY", message });
4626
+ setIsSubmitting(false);
4627
+ return;
4628
+ }
4629
+ const checkout = elementsRef.current.processCheckout({
4630
+ cart_id: resolvedCartId,
4631
+ location_id: locationId ?? client.getLocationId() ?? void 0,
4632
+ order_type: orderType,
4633
+ enroll_in_link: enrollInLink,
4634
+ on_status_change: emitStatus,
4635
+ pay_currency: fxOptions?.displayCurrency
4636
+ });
4637
+ activeCheckoutRef.current = checkout;
4638
+ try {
4639
+ const result = await checkout;
4640
+ if (result.success) {
4641
+ onComplete(result);
4571
4642
  return;
4572
4643
  }
4573
- const nextBusiness = businessResult.ok ? businessResult.value : null;
4574
- const nextLocations = locationsResult.ok && Array.isArray(locationsResult.value) ? locationsResult.value : [];
4575
- const initialLocation = resolveInitialLocation(nextLocations);
4576
- setBusiness(nextBusiness);
4577
- if (nextBusiness?.id) {
4578
- resolvedClient.setBusinessId(nextBusiness.id);
4579
- }
4580
- setLocations(nextLocations);
4581
- if (initialLocation) {
4582
- setCurrentLocationState(initialLocation);
4583
- resolvedClient.setLocationId(initialLocation.id);
4584
- setStoredLocationId(initialLocation.id);
4585
- } else {
4586
- setCurrentLocationState(null);
4587
- resolvedClient.setLocationId(null);
4588
- setStoredLocationId(null);
4644
+ const code = result.error?.code || "CHECKOUT_FAILED";
4645
+ const message = result.error?.message || "Payment failed.";
4646
+ setErrorMessage(message);
4647
+ fireError({ code, message });
4648
+ } finally {
4649
+ if (isMountedRef.current) {
4650
+ activeCheckoutRef.current = null;
4651
+ setIsSubmitting(false);
4589
4652
  }
4590
- setIsReady(true);
4591
4653
  }
4592
- bootstrap().catch(() => {
4593
- if (cancelled) {
4594
- return;
4654
+ });
4655
+ React3.useEffect(() => {
4656
+ if (isDemoCheckout || !resolvedBusinessId) {
4657
+ elementsRef.current = null;
4658
+ return;
4659
+ }
4660
+ const elements = client.elements(resolvedBusinessId, {
4661
+ appearance: initialAppearanceRef.current,
4662
+ linkUrl
4663
+ });
4664
+ elementsRef.current = elements;
4665
+ const checkout = elements.create("checkout", {
4666
+ orderTypes: resolvedOrderTypes,
4667
+ defaultOrderType: resolvedOrderTypes[0]
4668
+ });
4669
+ if (checkoutMountRef.current) {
4670
+ checkout.mount(checkoutMountRef.current);
4671
+ }
4672
+ checkout.on("ready", () => {
4673
+ const cart = resolvedCartRef.current;
4674
+ if (cart) {
4675
+ checkout.setCart(transformToCheckoutCart(cart, fxOptionsRef.current));
4595
4676
  }
4596
- setBusiness(null);
4597
- setLocations([]);
4598
- setCurrentLocationState(null);
4599
- resolvedClient.setLocationId(null);
4600
- setStoredLocationId(null);
4601
- setIsReady(true);
4677
+ });
4678
+ checkout.on("order_type_changed", (data) => {
4679
+ const typed = data;
4680
+ if (typed.orderType) {
4681
+ setOrderType(typed.orderType);
4682
+ }
4683
+ });
4684
+ checkout.on("request_submit", () => {
4685
+ void handleSubmit();
4602
4686
  });
4603
4687
  return () => {
4604
- cancelled = true;
4688
+ activeCheckoutRef.current?.abort();
4689
+ activeCheckoutRef.current = null;
4690
+ elements.destroy();
4691
+ elementsRef.current = null;
4605
4692
  };
4606
- }, [resolvedClient, isDemoMode]);
4607
- const contextValue = React2.useMemo(
4608
- () => ({
4609
- client: resolvedClient,
4610
- business,
4611
- currency: baseCurrency,
4612
- country: business?.country_code || DEFAULT_COUNTRY,
4613
- locations,
4614
- currentLocation,
4615
- setCurrentLocation,
4616
- isReady,
4617
- isDemoMode,
4618
- baseCurrency,
4619
- displayCurrency,
4620
- setDisplayCurrency,
4621
- convertPrice,
4622
- fxRate
4623
- }),
4624
- [
4625
- resolvedClient,
4626
- business,
4627
- baseCurrency,
4628
- locations,
4629
- currentLocation,
4630
- setCurrentLocation,
4631
- isReady,
4632
- isDemoMode,
4633
- displayCurrency,
4634
- setDisplayCurrency,
4635
- convertPrice,
4636
- fxRate
4637
- ]
4638
- );
4639
- return /* @__PURE__ */ jsxRuntime.jsx(CimplifyContext.Provider, { value: contextValue, children });
4640
- }
4641
- function useCimplify() {
4642
- const context = React2.useContext(CimplifyContext);
4643
- if (!context) {
4644
- throw new Error("useCimplify must be used within CimplifyProvider");
4693
+ }, [client, resolvedBusinessId, isDemoCheckout]);
4694
+ React3.useEffect(() => {
4695
+ if (!resolvedCart || !elementsRef.current) return;
4696
+ const checkoutElement = elementsRef.current.getElement("checkout");
4697
+ if (checkoutElement) {
4698
+ checkoutElement.setCart(transformToCheckoutCart(resolvedCart, fxOptions));
4699
+ }
4700
+ }, [resolvedCart, fxOptions]);
4701
+ const colors = shellColors(isDark ?? false, primaryColor);
4702
+ if (isInitializing) {
4703
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className, "data-cimplify-checkout": "", children: /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-status": "", style: { fontSize: 13, color: colors.textSecondary }, children: "Preparing checkout..." }) });
4645
4704
  }
4646
- return context;
4647
- }
4648
- function useOptionalCimplify() {
4649
- return React2.useContext(CimplifyContext);
4705
+ if (!isDemoCheckout && (!resolvedBusinessId || !resolvedCartId)) {
4706
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className, "data-cimplify-checkout": "", children: /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-error": "", style: { fontSize: 13, color: colors.error }, children: errorMessage || "Unable to initialize checkout. Please refresh and try again." }) });
4707
+ }
4708
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, "data-cimplify-checkout": "", children: [
4709
+ isTestMode && !isDemoCheckout && /* @__PURE__ */ jsxRuntime.jsx(
4710
+ "p",
4711
+ {
4712
+ "data-cimplify-test-mode": "",
4713
+ style: {
4714
+ marginBottom: "10px",
4715
+ fontSize: "12px",
4716
+ fontWeight: 600,
4717
+ color: "#92400e"
4718
+ },
4719
+ children: "Test mode - no real charges"
4720
+ }
4721
+ ),
4722
+ /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-section": "checkout", children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: isDemoCheckout ? void 0 : checkoutMountRef }) }),
4723
+ status && /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-status": "", style: { marginTop: SPACE.sm, fontSize: 13, color: colors.textSecondary }, children: statusText || statusToLabel(status) }),
4724
+ errorMessage && /* @__PURE__ */ jsxRuntime.jsx("p", { "data-cimplify-error": "", style: { marginTop: SPACE.sm, fontSize: 13, color: colors.error }, children: errorMessage })
4725
+ ] });
4650
4726
  }
4651
4727
  function Price({ amount, className, prefix }) {
4652
4728
  const { displayCurrency, convertPrice } = useCimplify();
@@ -4672,9 +4748,9 @@ function useProducts(options = {}) {
4672
4748
  }
4673
4749
  const enabled = options.enabled ?? true;
4674
4750
  const locationId = client.getLocationId();
4675
- const previousLocationIdRef = React2.useRef(locationId);
4676
- const requestIdRef = React2.useRef(0);
4677
- const queryOptions = React2.useMemo(
4751
+ const previousLocationIdRef = React3.useRef(locationId);
4752
+ const requestIdRef = React3.useRef(0);
4753
+ const queryOptions = React3.useMemo(
4678
4754
  () => ({
4679
4755
  category: options.category,
4680
4756
  collection: options.collection,
@@ -4684,25 +4760,25 @@ function useProducts(options = {}) {
4684
4760
  }),
4685
4761
  [options.category, options.collection, options.featured, options.limit, options.search]
4686
4762
  );
4687
- const cacheKey = React2.useMemo(
4763
+ const cacheKey = React3.useMemo(
4688
4764
  () => buildProductsCacheKey(client, locationId, queryOptions),
4689
4765
  [client, locationId, queryOptions]
4690
4766
  );
4691
4767
  const cached = productsCache.get(cacheKey);
4692
- const [products, setProducts] = React2.useState(cached?.products ?? []);
4693
- const [isComplete, setIsComplete] = React2.useState(cached?.is_complete ?? true);
4694
- const [totalAvailable, setTotalAvailable] = React2.useState(cached?.total_available);
4695
- const [pagination, setPagination] = React2.useState(cached?.pagination);
4696
- const [isLoading, setIsLoading] = React2.useState(enabled && !cached);
4697
- const [error, setError] = React2.useState(null);
4698
- React2.useEffect(() => {
4768
+ const [products, setProducts] = React3.useState(cached?.products ?? []);
4769
+ const [isComplete, setIsComplete] = React3.useState(cached?.is_complete ?? true);
4770
+ const [totalAvailable, setTotalAvailable] = React3.useState(cached?.total_available);
4771
+ const [pagination, setPagination] = React3.useState(cached?.pagination);
4772
+ const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
4773
+ const [error, setError] = React3.useState(null);
4774
+ React3.useEffect(() => {
4699
4775
  if (previousLocationIdRef.current !== locationId) {
4700
4776
  productsCache.clear();
4701
4777
  productsInflight.clear();
4702
4778
  previousLocationIdRef.current = locationId;
4703
4779
  }
4704
4780
  }, [locationId]);
4705
- const load = React2.useCallback(
4781
+ const load = React3.useCallback(
4706
4782
  async (force = false) => {
4707
4783
  if (!enabled) {
4708
4784
  setIsLoading(false);
@@ -4765,10 +4841,10 @@ function useProducts(options = {}) {
4765
4841
  },
4766
4842
  [cacheKey, client, enabled, queryOptions]
4767
4843
  );
4768
- React2.useEffect(() => {
4844
+ React3.useEffect(() => {
4769
4845
  void load(false);
4770
4846
  }, [load]);
4771
- const refetch = React2.useCallback(async () => {
4847
+ const refetch = React3.useCallback(async () => {
4772
4848
  productsCache.delete(cacheKey);
4773
4849
  await load(true);
4774
4850
  }, [cacheKey, load]);
@@ -4802,27 +4878,27 @@ function useProduct(slugOrId, options = {}) {
4802
4878
  }
4803
4879
  const enabled = options.enabled ?? true;
4804
4880
  const locationId = client.getLocationId();
4805
- const previousLocationIdRef = React2.useRef(locationId);
4806
- const requestIdRef = React2.useRef(0);
4807
- const normalizedSlugOrId = React2.useMemo(() => (slugOrId || "").trim(), [slugOrId]);
4808
- const cacheKey = React2.useMemo(
4881
+ const previousLocationIdRef = React3.useRef(locationId);
4882
+ const requestIdRef = React3.useRef(0);
4883
+ const normalizedSlugOrId = React3.useMemo(() => (slugOrId || "").trim(), [slugOrId]);
4884
+ const cacheKey = React3.useMemo(
4809
4885
  () => buildProductCacheKey(client, locationId, normalizedSlugOrId),
4810
4886
  [client, locationId, normalizedSlugOrId]
4811
4887
  );
4812
4888
  const cached = productCache.get(cacheKey);
4813
- const [product, setProduct] = React2.useState(cached?.product ?? null);
4814
- const [isLoading, setIsLoading] = React2.useState(
4889
+ const [product, setProduct] = React3.useState(cached?.product ?? null);
4890
+ const [isLoading, setIsLoading] = React3.useState(
4815
4891
  enabled && normalizedSlugOrId.length > 0 && !cached
4816
4892
  );
4817
- const [error, setError] = React2.useState(null);
4818
- React2.useEffect(() => {
4893
+ const [error, setError] = React3.useState(null);
4894
+ React3.useEffect(() => {
4819
4895
  if (previousLocationIdRef.current !== locationId) {
4820
4896
  productCache.clear();
4821
4897
  productInflight.clear();
4822
4898
  previousLocationIdRef.current = locationId;
4823
4899
  }
4824
4900
  }, [locationId]);
4825
- const load = React2.useCallback(
4901
+ const load = React3.useCallback(
4826
4902
  async (force = false) => {
4827
4903
  if (!enabled || normalizedSlugOrId.length === 0) {
4828
4904
  setProduct(null);
@@ -4875,10 +4951,10 @@ function useProduct(slugOrId, options = {}) {
4875
4951
  },
4876
4952
  [cacheKey, client, enabled, normalizedSlugOrId]
4877
4953
  );
4878
- React2.useEffect(() => {
4954
+ React3.useEffect(() => {
4879
4955
  void load(false);
4880
4956
  }, [load]);
4881
- const refetch = React2.useCallback(async () => {
4957
+ const refetch = React3.useCallback(async () => {
4882
4958
  productCache.delete(cacheKey);
4883
4959
  await load(true);
4884
4960
  }, [cacheKey, load]);
@@ -4896,12 +4972,12 @@ function useCategories(options = {}) {
4896
4972
  throw new Error("useCategories must be used within CimplifyProvider or passed { client }.");
4897
4973
  }
4898
4974
  const enabled = options.enabled ?? true;
4899
- const cacheKey = React2.useMemo(() => buildCategoriesCacheKey(client), [client]);
4975
+ const cacheKey = React3.useMemo(() => buildCategoriesCacheKey(client), [client]);
4900
4976
  const cached = categoriesCache.get(cacheKey);
4901
- const [categories, setCategories] = React2.useState(cached ?? []);
4902
- const [isLoading, setIsLoading] = React2.useState(enabled && !cached);
4903
- const [error, setError] = React2.useState(null);
4904
- const load = React2.useCallback(
4977
+ const [categories, setCategories] = React3.useState(cached ?? []);
4978
+ const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
4979
+ const [error, setError] = React3.useState(null);
4980
+ const load = React3.useCallback(
4905
4981
  async (force = false) => {
4906
4982
  if (!enabled) {
4907
4983
  setIsLoading(false);
@@ -4945,10 +5021,10 @@ function useCategories(options = {}) {
4945
5021
  },
4946
5022
  [cacheKey, client, enabled]
4947
5023
  );
4948
- React2.useEffect(() => {
5024
+ React3.useEffect(() => {
4949
5025
  void load(false);
4950
5026
  }, [load]);
4951
- const refetch = React2.useCallback(async () => {
5027
+ const refetch = React3.useCallback(async () => {
4952
5028
  categoriesCache.delete(cacheKey);
4953
5029
  await load(true);
4954
5030
  }, [cacheKey, load]);
@@ -5469,7 +5545,7 @@ function useCart(options = {}) {
5469
5545
  const locationId = options.locationId ?? client.getLocationId();
5470
5546
  const isDemoMode = options.demoMode ?? context?.isDemoMode ?? client.getPublicKey().trim().length === 0;
5471
5547
  const currency = options.currency ?? context?.currency ?? "USD";
5472
- const store = React2.useMemo(
5548
+ const store = React3.useMemo(
5473
5549
  () => getOrCreateStore({
5474
5550
  client,
5475
5551
  locationId,
@@ -5478,43 +5554,43 @@ function useCart(options = {}) {
5478
5554
  }),
5479
5555
  [client, currency, isDemoMode, locationId]
5480
5556
  );
5481
- const snapshot = React2.useSyncExternalStore(
5557
+ const snapshot = React3.useSyncExternalStore(
5482
5558
  store.subscribe,
5483
5559
  store.getSnapshot,
5484
5560
  store.getSnapshot
5485
5561
  );
5486
- React2.useEffect(() => {
5562
+ React3.useEffect(() => {
5487
5563
  void store.initialize();
5488
5564
  }, [store]);
5489
- const addItem = React2.useCallback(
5565
+ const addItem = React3.useCallback(
5490
5566
  async (product, quantity, addOptions) => {
5491
5567
  await store.addItem(product, quantity, addOptions);
5492
5568
  },
5493
5569
  [store]
5494
5570
  );
5495
- const removeItem = React2.useCallback(
5571
+ const removeItem = React3.useCallback(
5496
5572
  async (itemId) => {
5497
5573
  await store.removeItem(itemId);
5498
5574
  },
5499
5575
  [store]
5500
5576
  );
5501
- const updateQuantity = React2.useCallback(
5577
+ const updateQuantity = React3.useCallback(
5502
5578
  async (itemId, quantity) => {
5503
5579
  await store.updateQuantity(itemId, quantity);
5504
5580
  },
5505
5581
  [store]
5506
5582
  );
5507
- const clearCart = React2.useCallback(async () => {
5583
+ const clearCart = React3.useCallback(async () => {
5508
5584
  await store.clearCart();
5509
5585
  }, [store]);
5510
- const sync = React2.useCallback(async () => {
5586
+ const sync = React3.useCallback(async () => {
5511
5587
  try {
5512
5588
  await store.sync();
5513
5589
  } catch (syncError) {
5514
5590
  throw syncError;
5515
5591
  }
5516
5592
  }, [store]);
5517
- const itemCount = React2.useMemo(
5593
+ const itemCount = React3.useMemo(
5518
5594
  () => snapshot.items.reduce((sum, item) => sum + item.quantity, 0),
5519
5595
  [snapshot.items]
5520
5596
  );
@@ -5545,22 +5621,22 @@ function useOrder(orderId, options = {}) {
5545
5621
  if (!client) {
5546
5622
  throw new Error("useOrder must be used within CimplifyProvider or passed { client }.");
5547
5623
  }
5548
- const normalizedOrderId = React2.useMemo(() => (orderId || "").trim(), [orderId]);
5624
+ const normalizedOrderId = React3.useMemo(() => (orderId || "").trim(), [orderId]);
5549
5625
  const enabled = options.enabled ?? true;
5550
5626
  const poll = options.poll ?? false;
5551
5627
  const pollInterval = options.pollInterval ?? 5e3;
5552
- const requestIdRef = React2.useRef(0);
5553
- const cacheKey = React2.useMemo(
5628
+ const requestIdRef = React3.useRef(0);
5629
+ const cacheKey = React3.useMemo(
5554
5630
  () => buildOrderCacheKey(client, normalizedOrderId),
5555
5631
  [client, normalizedOrderId]
5556
5632
  );
5557
5633
  const cached = orderCache.get(cacheKey);
5558
- const [order, setOrder] = React2.useState(cached?.order ?? null);
5559
- const [isLoading, setIsLoading] = React2.useState(
5634
+ const [order, setOrder] = React3.useState(cached?.order ?? null);
5635
+ const [isLoading, setIsLoading] = React3.useState(
5560
5636
  enabled && normalizedOrderId.length > 0 && !cached
5561
5637
  );
5562
- const [error, setError] = React2.useState(null);
5563
- const load = React2.useCallback(
5638
+ const [error, setError] = React3.useState(null);
5639
+ const load = React3.useCallback(
5564
5640
  async (force = false) => {
5565
5641
  if (!enabled || normalizedOrderId.length === 0) {
5566
5642
  setOrder(null);
@@ -5613,10 +5689,10 @@ function useOrder(orderId, options = {}) {
5613
5689
  },
5614
5690
  [cacheKey, client, enabled, normalizedOrderId]
5615
5691
  );
5616
- React2.useEffect(() => {
5692
+ React3.useEffect(() => {
5617
5693
  void load(false);
5618
5694
  }, [load]);
5619
- React2.useEffect(() => {
5695
+ React3.useEffect(() => {
5620
5696
  if (!poll || !enabled || normalizedOrderId.length === 0) {
5621
5697
  return;
5622
5698
  }
@@ -5627,7 +5703,7 @@ function useOrder(orderId, options = {}) {
5627
5703
  window.clearInterval(timer);
5628
5704
  };
5629
5705
  }, [enabled, load, normalizedOrderId.length, poll, pollInterval]);
5630
- const refetch = React2.useCallback(async () => {
5706
+ const refetch = React3.useCallback(async () => {
5631
5707
  orderCache.delete(cacheKey);
5632
5708
  await load(true);
5633
5709
  }, [cacheKey, load]);
@@ -5678,10 +5754,10 @@ function useLocations(options = {}) {
5678
5754
  };
5679
5755
  }
5680
5756
  const client = options.client;
5681
- const [locations, setLocations] = React2.useState([]);
5682
- const [currentLocation, setCurrentLocationState] = React2.useState(null);
5683
- const [isLoading, setIsLoading] = React2.useState(true);
5684
- const setCurrentLocation = React2.useCallback(
5757
+ const [locations, setLocations] = React3.useState([]);
5758
+ const [currentLocation, setCurrentLocationState] = React3.useState(null);
5759
+ const [isLoading, setIsLoading] = React3.useState(true);
5760
+ const setCurrentLocation = React3.useCallback(
5685
5761
  (location) => {
5686
5762
  setCurrentLocationState(location);
5687
5763
  if (client) {
@@ -5691,7 +5767,7 @@ function useLocations(options = {}) {
5691
5767
  },
5692
5768
  [client]
5693
5769
  );
5694
- React2.useEffect(() => {
5770
+ React3.useEffect(() => {
5695
5771
  if (!client) {
5696
5772
  setLocations([]);
5697
5773
  setCurrentLocationState(null);
@@ -5749,24 +5825,24 @@ function useCollections(options = {}) {
5749
5825
  }
5750
5826
  const enabled = options.enabled ?? true;
5751
5827
  const locationId = client.getLocationId();
5752
- const previousLocationIdRef = React2.useRef(locationId);
5753
- const requestIdRef = React2.useRef(0);
5754
- const cacheKey = React2.useMemo(
5828
+ const previousLocationIdRef = React3.useRef(locationId);
5829
+ const requestIdRef = React3.useRef(0);
5830
+ const cacheKey = React3.useMemo(
5755
5831
  () => buildCollectionsCacheKey(client, locationId),
5756
5832
  [client, locationId]
5757
5833
  );
5758
5834
  const cached = collectionsCache.get(cacheKey);
5759
- const [collections, setCollections] = React2.useState(cached?.collections ?? []);
5760
- const [isLoading, setIsLoading] = React2.useState(enabled && !cached);
5761
- const [error, setError] = React2.useState(null);
5762
- React2.useEffect(() => {
5835
+ const [collections, setCollections] = React3.useState(cached?.collections ?? []);
5836
+ const [isLoading, setIsLoading] = React3.useState(enabled && !cached);
5837
+ const [error, setError] = React3.useState(null);
5838
+ React3.useEffect(() => {
5763
5839
  if (previousLocationIdRef.current !== locationId) {
5764
5840
  collectionsCache.clear();
5765
5841
  collectionsInflight.clear();
5766
5842
  previousLocationIdRef.current = locationId;
5767
5843
  }
5768
5844
  }, [locationId]);
5769
- const load = React2.useCallback(
5845
+ const load = React3.useCallback(
5770
5846
  async (force = false) => {
5771
5847
  if (!enabled) {
5772
5848
  setIsLoading(false);
@@ -5816,10 +5892,10 @@ function useCollections(options = {}) {
5816
5892
  },
5817
5893
  [cacheKey, client, enabled]
5818
5894
  );
5819
- React2.useEffect(() => {
5895
+ React3.useEffect(() => {
5820
5896
  void load(false);
5821
5897
  }, [load]);
5822
- const refetch = React2.useCallback(async () => {
5898
+ const refetch = React3.useCallback(async () => {
5823
5899
  collectionsCache.delete(cacheKey);
5824
5900
  await load(true);
5825
5901
  }, [cacheKey, load]);
@@ -5845,28 +5921,28 @@ function useCollection(idOrSlug, options = {}) {
5845
5921
  }
5846
5922
  const enabled = options.enabled ?? true;
5847
5923
  const locationId = client.getLocationId();
5848
- const previousLocationIdRef = React2.useRef(locationId);
5849
- const requestIdRef = React2.useRef(0);
5850
- const normalizedIdOrSlug = React2.useMemo(() => (idOrSlug || "").trim(), [idOrSlug]);
5851
- const cacheKey = React2.useMemo(
5924
+ const previousLocationIdRef = React3.useRef(locationId);
5925
+ const requestIdRef = React3.useRef(0);
5926
+ const normalizedIdOrSlug = React3.useMemo(() => (idOrSlug || "").trim(), [idOrSlug]);
5927
+ const cacheKey = React3.useMemo(
5852
5928
  () => buildCollectionCacheKey(client, locationId, normalizedIdOrSlug),
5853
5929
  [client, locationId, normalizedIdOrSlug]
5854
5930
  );
5855
5931
  const cached = collectionCache.get(cacheKey);
5856
- const [collection, setCollection] = React2.useState(cached?.collection ?? null);
5857
- const [products, setProducts] = React2.useState(cached?.products ?? []);
5858
- const [isLoading, setIsLoading] = React2.useState(
5932
+ const [collection, setCollection] = React3.useState(cached?.collection ?? null);
5933
+ const [products, setProducts] = React3.useState(cached?.products ?? []);
5934
+ const [isLoading, setIsLoading] = React3.useState(
5859
5935
  enabled && normalizedIdOrSlug.length > 0 && !cached
5860
5936
  );
5861
- const [error, setError] = React2.useState(null);
5862
- React2.useEffect(() => {
5937
+ const [error, setError] = React3.useState(null);
5938
+ React3.useEffect(() => {
5863
5939
  if (previousLocationIdRef.current !== locationId) {
5864
5940
  collectionCache.clear();
5865
5941
  collectionInflight.clear();
5866
5942
  previousLocationIdRef.current = locationId;
5867
5943
  }
5868
5944
  }, [locationId]);
5869
- const load = React2.useCallback(
5945
+ const load = React3.useCallback(
5870
5946
  async (force = false) => {
5871
5947
  if (!enabled || normalizedIdOrSlug.length === 0) {
5872
5948
  setCollection(null);
@@ -5929,10 +6005,10 @@ function useCollection(idOrSlug, options = {}) {
5929
6005
  },
5930
6006
  [cacheKey, client, enabled, normalizedIdOrSlug]
5931
6007
  );
5932
- React2.useEffect(() => {
6008
+ React3.useEffect(() => {
5933
6009
  void load(false);
5934
6010
  }, [load]);
5935
- const refetch = React2.useCallback(async () => {
6011
+ const refetch = React3.useCallback(async () => {
5936
6012
  collectionCache.delete(cacheKey);
5937
6013
  await load(true);
5938
6014
  }, [cacheKey, load]);
@@ -5958,27 +6034,27 @@ function useBundle(idOrSlug, options = {}) {
5958
6034
  }
5959
6035
  const enabled = options.enabled ?? true;
5960
6036
  const locationId = client.getLocationId();
5961
- const previousLocationIdRef = React2.useRef(locationId);
5962
- const requestIdRef = React2.useRef(0);
5963
- const normalizedIdOrSlug = React2.useMemo(() => (idOrSlug || "").trim(), [idOrSlug]);
5964
- const cacheKey = React2.useMemo(
6037
+ const previousLocationIdRef = React3.useRef(locationId);
6038
+ const requestIdRef = React3.useRef(0);
6039
+ const normalizedIdOrSlug = React3.useMemo(() => (idOrSlug || "").trim(), [idOrSlug]);
6040
+ const cacheKey = React3.useMemo(
5965
6041
  () => buildBundleCacheKey(client, locationId, normalizedIdOrSlug),
5966
6042
  [client, locationId, normalizedIdOrSlug]
5967
6043
  );
5968
6044
  const cached = bundleCache.get(cacheKey);
5969
- const [bundle, setBundle] = React2.useState(cached?.bundle ?? null);
5970
- const [isLoading, setIsLoading] = React2.useState(
6045
+ const [bundle, setBundle] = React3.useState(cached?.bundle ?? null);
6046
+ const [isLoading, setIsLoading] = React3.useState(
5971
6047
  enabled && normalizedIdOrSlug.length > 0 && !cached
5972
6048
  );
5973
- const [error, setError] = React2.useState(null);
5974
- React2.useEffect(() => {
6049
+ const [error, setError] = React3.useState(null);
6050
+ React3.useEffect(() => {
5975
6051
  if (previousLocationIdRef.current !== locationId) {
5976
6052
  bundleCache.clear();
5977
6053
  bundleInflight.clear();
5978
6054
  previousLocationIdRef.current = locationId;
5979
6055
  }
5980
6056
  }, [locationId]);
5981
- const load = React2.useCallback(
6057
+ const load = React3.useCallback(
5982
6058
  async (force = false) => {
5983
6059
  if (!enabled || normalizedIdOrSlug.length === 0) {
5984
6060
  setBundle(null);
@@ -6029,10 +6105,10 @@ function useBundle(idOrSlug, options = {}) {
6029
6105
  },
6030
6106
  [cacheKey, client, enabled, normalizedIdOrSlug]
6031
6107
  );
6032
- React2.useEffect(() => {
6108
+ React3.useEffect(() => {
6033
6109
  void load(false);
6034
6110
  }, [load]);
6035
- const refetch = React2.useCallback(async () => {
6111
+ const refetch = React3.useCallback(async () => {
6036
6112
  bundleCache.delete(cacheKey);
6037
6113
  await load(true);
6038
6114
  }, [cacheKey, load]);
@@ -6062,37 +6138,37 @@ function useComposite(idOrProductId, options = {}) {
6062
6138
  }
6063
6139
  const enabled = options.enabled ?? true;
6064
6140
  const locationId = client.getLocationId();
6065
- const previousLocationIdRef = React2.useRef(locationId);
6066
- const requestIdRef = React2.useRef(0);
6067
- const priceRequestIdRef = React2.useRef(0);
6068
- const normalizedIdOrProductId = React2.useMemo(
6141
+ const previousLocationIdRef = React3.useRef(locationId);
6142
+ const requestIdRef = React3.useRef(0);
6143
+ const priceRequestIdRef = React3.useRef(0);
6144
+ const normalizedIdOrProductId = React3.useMemo(
6069
6145
  () => (idOrProductId || "").trim(),
6070
6146
  [idOrProductId]
6071
6147
  );
6072
- const byProductId = React2.useMemo(
6148
+ const byProductId = React3.useMemo(
6073
6149
  () => shouldFetchByProductId(normalizedIdOrProductId, options.byProductId),
6074
6150
  [normalizedIdOrProductId, options.byProductId]
6075
6151
  );
6076
- const cacheKey = React2.useMemo(
6152
+ const cacheKey = React3.useMemo(
6077
6153
  () => buildCompositeCacheKey(client, locationId, normalizedIdOrProductId, byProductId),
6078
6154
  [byProductId, client, locationId, normalizedIdOrProductId]
6079
6155
  );
6080
6156
  const cached = compositeCache.get(cacheKey);
6081
- const [composite, setComposite] = React2.useState(cached?.composite ?? null);
6082
- const [isLoading, setIsLoading] = React2.useState(
6157
+ const [composite, setComposite] = React3.useState(cached?.composite ?? null);
6158
+ const [isLoading, setIsLoading] = React3.useState(
6083
6159
  enabled && normalizedIdOrProductId.length > 0 && !cached
6084
6160
  );
6085
- const [error, setError] = React2.useState(null);
6086
- const [priceResult, setPriceResult] = React2.useState(null);
6087
- const [isPriceLoading, setIsPriceLoading] = React2.useState(false);
6088
- React2.useEffect(() => {
6161
+ const [error, setError] = React3.useState(null);
6162
+ const [priceResult, setPriceResult] = React3.useState(null);
6163
+ const [isPriceLoading, setIsPriceLoading] = React3.useState(false);
6164
+ React3.useEffect(() => {
6089
6165
  if (previousLocationIdRef.current !== locationId) {
6090
6166
  compositeCache.clear();
6091
6167
  compositeInflight.clear();
6092
6168
  previousLocationIdRef.current = locationId;
6093
6169
  }
6094
6170
  }, [locationId]);
6095
- const load = React2.useCallback(
6171
+ const load = React3.useCallback(
6096
6172
  async (force = false) => {
6097
6173
  if (!enabled || normalizedIdOrProductId.length === 0) {
6098
6174
  setComposite(null);
@@ -6145,10 +6221,10 @@ function useComposite(idOrProductId, options = {}) {
6145
6221
  },
6146
6222
  [byProductId, cacheKey, client, enabled, normalizedIdOrProductId]
6147
6223
  );
6148
- React2.useEffect(() => {
6224
+ React3.useEffect(() => {
6149
6225
  void load(false);
6150
6226
  }, [load]);
6151
- const calculatePrice = React2.useCallback(
6227
+ const calculatePrice = React3.useCallback(
6152
6228
  async (selections, overrideLocationId) => {
6153
6229
  if (!composite) {
6154
6230
  return null;
@@ -6182,7 +6258,7 @@ function useComposite(idOrProductId, options = {}) {
6182
6258
  },
6183
6259
  [client, composite]
6184
6260
  );
6185
- const refetch = React2.useCallback(async () => {
6261
+ const refetch = React3.useCallback(async () => {
6186
6262
  compositeCache.delete(cacheKey);
6187
6263
  await load(true);
6188
6264
  }, [cacheKey, load]);
@@ -6197,13 +6273,13 @@ function useSearch(options = {}) {
6197
6273
  const minLength = Math.max(0, options.minLength ?? 2);
6198
6274
  const debounceMs = Math.max(0, options.debounceMs ?? 300);
6199
6275
  const limit = Math.max(1, options.limit ?? 20);
6200
- const [query, setQueryState] = React2.useState("");
6201
- const [results, setResults] = React2.useState([]);
6202
- const [isLoading, setIsLoading] = React2.useState(false);
6203
- const [error, setError] = React2.useState(null);
6204
- const requestIdRef = React2.useRef(0);
6205
- const timerRef = React2.useRef(null);
6206
- React2.useEffect(() => {
6276
+ const [query, setQueryState] = React3.useState("");
6277
+ const [results, setResults] = React3.useState([]);
6278
+ const [isLoading, setIsLoading] = React3.useState(false);
6279
+ const [error, setError] = React3.useState(null);
6280
+ const requestIdRef = React3.useRef(0);
6281
+ const timerRef = React3.useRef(null);
6282
+ React3.useEffect(() => {
6207
6283
  if (timerRef.current) {
6208
6284
  clearTimeout(timerRef.current);
6209
6285
  timerRef.current = null;
@@ -6250,10 +6326,10 @@ function useSearch(options = {}) {
6250
6326
  }
6251
6327
  };
6252
6328
  }, [client, debounceMs, limit, minLength, options.category, query]);
6253
- const setQuery = React2.useCallback((nextQuery) => {
6329
+ const setQuery = React3.useCallback((nextQuery) => {
6254
6330
  setQueryState(nextQuery);
6255
6331
  }, []);
6256
- const clear = React2.useCallback(() => {
6332
+ const clear = React3.useCallback(() => {
6257
6333
  requestIdRef.current += 1;
6258
6334
  if (timerRef.current) {
6259
6335
  clearTimeout(timerRef.current);
@@ -6309,28 +6385,28 @@ function useQuote(input, options = {}) {
6309
6385
  const autoRefresh = options.autoRefresh ?? true;
6310
6386
  const refreshBeforeExpiryMs = Math.max(0, options.refreshBeforeExpiryMs ?? 3e4);
6311
6387
  const locationId = client.getLocationId();
6312
- const requestIdRef = React2.useRef(0);
6313
- const refreshTimerRef = React2.useRef(null);
6314
- const expiryTimerRef = React2.useRef(null);
6315
- const inputSignature = React2.useMemo(() => JSON.stringify(input ?? null), [input]);
6316
- const normalizedInput = React2.useMemo(() => {
6388
+ const requestIdRef = React3.useRef(0);
6389
+ const refreshTimerRef = React3.useRef(null);
6390
+ const expiryTimerRef = React3.useRef(null);
6391
+ const inputSignature = React3.useMemo(() => JSON.stringify(input ?? null), [input]);
6392
+ const normalizedInput = React3.useMemo(() => {
6317
6393
  if (!input) {
6318
6394
  return null;
6319
6395
  }
6320
6396
  const normalized = normalizeInput(input, locationId);
6321
6397
  return normalized.product_id.length > 0 ? normalized : null;
6322
6398
  }, [inputSignature, locationId]);
6323
- const cacheKey = React2.useMemo(
6399
+ const cacheKey = React3.useMemo(
6324
6400
  () => buildQuoteCacheKey(client, locationId, inputSignature),
6325
6401
  [client, inputSignature, locationId]
6326
6402
  );
6327
6403
  const cached = quoteCache.get(cacheKey);
6328
- const [quote, setQuote] = React2.useState(cached?.quote ?? null);
6329
- const [isLoading, setIsLoading] = React2.useState(enabled && normalizedInput !== null && !cached);
6330
- const [error, setError] = React2.useState(null);
6331
- const [isExpired, setIsExpired] = React2.useState(isQuoteExpired(cached?.quote ?? null));
6332
- const [messages, setMessages] = React2.useState(cached?.quote?.ui_messages ?? []);
6333
- const load = React2.useCallback(
6404
+ const [quote, setQuote] = React3.useState(cached?.quote ?? null);
6405
+ const [isLoading, setIsLoading] = React3.useState(enabled && normalizedInput !== null && !cached);
6406
+ const [error, setError] = React3.useState(null);
6407
+ const [isExpired, setIsExpired] = React3.useState(isQuoteExpired(cached?.quote ?? null));
6408
+ const [messages, setMessages] = React3.useState(cached?.quote?.ui_messages ?? []);
6409
+ const load = React3.useCallback(
6334
6410
  async (force = false) => {
6335
6411
  if (!enabled || !normalizedInput) {
6336
6412
  setQuote(null);
@@ -6388,10 +6464,10 @@ function useQuote(input, options = {}) {
6388
6464
  },
6389
6465
  [cacheKey, client, enabled, normalizedInput]
6390
6466
  );
6391
- React2.useEffect(() => {
6467
+ React3.useEffect(() => {
6392
6468
  void load(false);
6393
6469
  }, [load]);
6394
- const refresh = React2.useCallback(async () => {
6470
+ const refresh = React3.useCallback(async () => {
6395
6471
  if (!enabled || !normalizedInput) {
6396
6472
  return;
6397
6473
  }
@@ -6428,7 +6504,7 @@ function useQuote(input, options = {}) {
6428
6504
  }
6429
6505
  }
6430
6506
  }, [cacheKey, client, enabled, load, normalizedInput, quote]);
6431
- React2.useEffect(() => {
6507
+ React3.useEffect(() => {
6432
6508
  if (expiryTimerRef.current) {
6433
6509
  clearTimeout(expiryTimerRef.current);
6434
6510
  expiryTimerRef.current = null;
@@ -6452,7 +6528,7 @@ function useQuote(input, options = {}) {
6452
6528
  }
6453
6529
  };
6454
6530
  }, [quote?.expires_at, quote?.quote_id]);
6455
- React2.useEffect(() => {
6531
+ React3.useEffect(() => {
6456
6532
  if (refreshTimerRef.current) {
6457
6533
  clearTimeout(refreshTimerRef.current);
6458
6534
  refreshTimerRef.current = null;
@@ -6477,15 +6553,15 @@ function useQuote(input, options = {}) {
6477
6553
  }, [autoRefresh, enabled, quote?.expires_at, quote?.quote_id, refresh, refreshBeforeExpiryMs]);
6478
6554
  return { quote, isLoading, error, refresh, isExpired, messages };
6479
6555
  }
6480
- var ElementsContext = React2.createContext({
6556
+ var ElementsContext = React3.createContext({
6481
6557
  elements: null,
6482
6558
  isReady: false
6483
6559
  });
6484
6560
  function useElements() {
6485
- return React2.useContext(ElementsContext).elements;
6561
+ return React3.useContext(ElementsContext).elements;
6486
6562
  }
6487
6563
  function useElementsReady() {
6488
- return React2.useContext(ElementsContext).isReady;
6564
+ return React3.useContext(ElementsContext).isReady;
6489
6565
  }
6490
6566
  function ElementsProvider({
6491
6567
  client,
@@ -6493,10 +6569,10 @@ function ElementsProvider({
6493
6569
  options,
6494
6570
  children
6495
6571
  }) {
6496
- const [elements, setElements] = React2.useState(null);
6497
- const [isReady, setIsReady] = React2.useState(false);
6498
- const initialOptionsRef = React2.useRef(options);
6499
- React2.useEffect(() => {
6572
+ const [elements, setElements] = React3.useState(null);
6573
+ const [isReady, setIsReady] = React3.useState(false);
6574
+ const initialOptionsRef = React3.useRef(options);
6575
+ React3.useEffect(() => {
6500
6576
  let cancelled = false;
6501
6577
  let instance = null;
6502
6578
  setIsReady(false);
@@ -6537,20 +6613,20 @@ function AuthElement({
6537
6613
  onRequiresOtp,
6538
6614
  onError
6539
6615
  }) {
6540
- const containerRef = React2.useRef(null);
6541
- const elementRef = React2.useRef(null);
6616
+ const containerRef = React3.useRef(null);
6617
+ const elementRef = React3.useRef(null);
6542
6618
  const elements = useElements();
6543
- const onReadyRef = React2.useRef(onReady);
6544
- const onAuthenticatedRef = React2.useRef(onAuthenticated);
6545
- const onRequiresOtpRef = React2.useRef(onRequiresOtp);
6546
- const onErrorRef = React2.useRef(onError);
6547
- React2.useEffect(() => {
6619
+ const onReadyRef = React3.useRef(onReady);
6620
+ const onAuthenticatedRef = React3.useRef(onAuthenticated);
6621
+ const onRequiresOtpRef = React3.useRef(onRequiresOtp);
6622
+ const onErrorRef = React3.useRef(onError);
6623
+ React3.useEffect(() => {
6548
6624
  onReadyRef.current = onReady;
6549
6625
  onAuthenticatedRef.current = onAuthenticated;
6550
6626
  onRequiresOtpRef.current = onRequiresOtp;
6551
6627
  onErrorRef.current = onError;
6552
6628
  }, [onReady, onAuthenticated, onRequiresOtp, onError]);
6553
- React2.useEffect(() => {
6629
+ React3.useEffect(() => {
6554
6630
  if (!elements || !containerRef.current) return;
6555
6631
  const element = elements.create(ELEMENT_TYPES.AUTH, { prefillEmail });
6556
6632
  elementRef.current = element;
@@ -6580,18 +6656,18 @@ function AddressElement({
6580
6656
  onChange,
6581
6657
  onError
6582
6658
  }) {
6583
- const containerRef = React2.useRef(null);
6584
- const elementRef = React2.useRef(null);
6659
+ const containerRef = React3.useRef(null);
6660
+ const elementRef = React3.useRef(null);
6585
6661
  const elements = useElements();
6586
- const onReadyRef = React2.useRef(onReady);
6587
- const onChangeRef = React2.useRef(onChange);
6588
- const onErrorRef = React2.useRef(onError);
6589
- React2.useEffect(() => {
6662
+ const onReadyRef = React3.useRef(onReady);
6663
+ const onChangeRef = React3.useRef(onChange);
6664
+ const onErrorRef = React3.useRef(onError);
6665
+ React3.useEffect(() => {
6590
6666
  onReadyRef.current = onReady;
6591
6667
  onChangeRef.current = onChange;
6592
6668
  onErrorRef.current = onError;
6593
6669
  }, [onReady, onChange, onError]);
6594
- React2.useEffect(() => {
6670
+ React3.useEffect(() => {
6595
6671
  if (!elements || !containerRef.current) return;
6596
6672
  const element = elements.create(ELEMENT_TYPES.ADDRESS, { mode });
6597
6673
  elementRef.current = element;
@@ -6618,18 +6694,18 @@ function PaymentElement({
6618
6694
  onChange,
6619
6695
  onError
6620
6696
  }) {
6621
- const containerRef = React2.useRef(null);
6622
- const elementRef = React2.useRef(null);
6697
+ const containerRef = React3.useRef(null);
6698
+ const elementRef = React3.useRef(null);
6623
6699
  const elements = useElements();
6624
- const onReadyRef = React2.useRef(onReady);
6625
- const onChangeRef = React2.useRef(onChange);
6626
- const onErrorRef = React2.useRef(onError);
6627
- React2.useEffect(() => {
6700
+ const onReadyRef = React3.useRef(onReady);
6701
+ const onChangeRef = React3.useRef(onChange);
6702
+ const onErrorRef = React3.useRef(onError);
6703
+ React3.useEffect(() => {
6628
6704
  onReadyRef.current = onReady;
6629
6705
  onChangeRef.current = onChange;
6630
6706
  onErrorRef.current = onError;
6631
6707
  }, [onReady, onChange, onError]);
6632
- React2.useEffect(() => {
6708
+ React3.useEffect(() => {
6633
6709
  if (!elements || !containerRef.current) return;
6634
6710
  const element = elements.create(ELEMENT_TYPES.PAYMENT, { amount, currency });
6635
6711
  elementRef.current = element;
@@ -6649,8 +6725,8 @@ function PaymentElement({
6649
6725
  }
6650
6726
  function useCheckout() {
6651
6727
  const elements = useElements();
6652
- const [isLoading, setIsLoading] = React2.useState(false);
6653
- const submit = React2.useCallback(
6728
+ const [isLoading, setIsLoading] = React3.useState(false);
6729
+ const submit = React3.useCallback(
6654
6730
  async (data) => {
6655
6731
  if (!elements) {
6656
6732
  return { success: false, error: { code: "NO_ELEMENTS", message: "Elements not initialized" } };
@@ -6664,7 +6740,7 @@ function useCheckout() {
6664
6740
  },
6665
6741
  [elements]
6666
6742
  );
6667
- const process = React2.useCallback(
6743
+ const process = React3.useCallback(
6668
6744
  async (options) => {
6669
6745
  if (!elements) {
6670
6746
  return {